Flora NeoPixel Ring Clock from the Learning System...

For RTC breakouts, etc., use the Other Products from Adafruit forum

Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.
Locked
User avatar
symo
 
Posts: 3
Joined: Wed Oct 10, 2012 6:21 pm

Flora NeoPixel Ring Clock from the Learning System...

Post by symo »

Hello all.

I have assembled all the parts and pieces for the Adafruit NeoPixel Ring Clock (with GPS.)
All the parts are as listed on the page, and all seems to be working great individually. :) (http://learn.adafruit.com/neopixel-ring-clock/overview)

The GPS responds as expected with the Adafruit test programs, and I have the NeoPixel rings working on their own as well.

My question is whether the code that is listed in the tutorial is functional. (http://learn.adafruit.com/neopixel-ring ... lock-faces)
I did a simple "Copy Code" and pasted it into my Arduino IDE, but things just don't work as expected.
In looking at the code, there seems to be several extra variables that aren't used in this project, and the inclusion of the Wire.h library... ??

I'm just wanting to make sure I'm not losing my mind. :) Any help will be greatly appreciated.

Thanks all!

-Jon

User avatar
symo
 
Posts: 3
Joined: Wed Oct 10, 2012 6:21 pm

Re: Flora NeoPixel Ring Clock from the Learning System...

Post by symo »

Ok, a minor update... I've cleaned up the code, and I can get the clock to work, but I never get a "fix" on the GPS. If I run the GPS code separately, I do get a fix.

I've now taken the cleaned up clock and GPS code and if I run it as intended, no "fix." If I just comment out the code that updates the neo pixels in the main loop(), I get a "fix."

Is this a timing issue with the GPS messages getting missed or something? I'm not running the millisecond LEDs as it is...

Any help is greatly appreciated.

By the way, I am running the external antenna with the GPS module. I currently have a Fix:1 Quality:2 Satellites:8

Thanks!
-Jon

User avatar
symo
 
Posts: 3
Joined: Wed Oct 10, 2012 6:21 pm

Re: Flora NeoPixel Ring Clock from the Learning System...

Post by symo »

I believe I have everything working now. :)

I think the issues were related to timing on the GPS messages coming from the GPS module.
I converted the code over to using interrupts, and I can now have the spinning millisecond animation and have the GPS "sync" properly.

I absolutely love Adafruit and everything they do to promote electronics. The community they have built is truly amazing! Thanks!

For those interested, here is the code I'm currently using:

Code: Select all

//NeoPixel clock with FLORA based on Kevin Alford's NeoPixel ring clock face
//https://github.com/zeroeth/time_loop
//http://www.youtube.com/watch?v=b-mROp-ZKuk
//modified by Becky Stern for Adafruit Industries
//further modified by Jon Simonds (basically just cleaned up some unneeded variables and took a little 
//           from here and there in the Adafruit example code, and have a functioning GPS NeoPixel clock. <GRIN> )

#include <Adafruit_GPS.h>
#include <Adafruit_NeoPixel.h>
#include <SoftwareSerial.h>
#include <Time.h>

Adafruit_GPS GPS(&Serial1);

#define PIN 12

// Set GPSECHO to 'false' to turn off echoing the GPS data to the Serial console
// Set to 'true' if you want to debug and listen to the raw GPS sentences
#define GPSECHO false
     
// this keeps track of whether we're using the interrupt
// off by default!
boolean usingInterrupt = false;

// From adaFruit NEOPIXEL goggles example: Gamma correction improves appearance of midrange colors
const uint8_t gamma[] = {
      0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
      0,  0,  0,  0,  0,  0,  0,  0,  1,  1,  1,  1,  1,  1,  1,  1,
      1,  1,  1,  1,  2,  2,  2,  2,  2,  2,  2,  2,  3,  3,  3,  3,
      3,  3,  4,  4,  4,  4,  5,  5,  5,  5,  5,  6,  6,  6,  6,  7,
      7,  7,  8,  8,  8,  9,  9,  9, 10, 10, 10, 11, 11, 11, 12, 12,
     13, 13, 13, 14, 14, 15, 15, 16, 16, 17, 17, 18, 18, 19, 19, 20,
     20, 21, 21, 22, 22, 23, 24, 24, 25, 25, 26, 27, 27, 28, 29, 29,
     30, 31, 31, 32, 33, 34, 34, 35, 36, 37, 38, 38, 39, 40, 41, 42,
     42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
     58, 59, 60, 61, 62, 63, 64, 65, 66, 68, 69, 70, 71, 72, 73, 75,
     76, 77, 78, 80, 81, 82, 84, 85, 86, 88, 89, 90, 92, 93, 94, 96,
     97, 99,100,102,103,105,106,108,109,111,112,114,115,117,119,120,
    122,124,125,127,129,130,132,134,136,137,139,141,143,145,146,148,
    150,152,154,156,158,160,162,164,166,168,170,172,174,176,178,180,
    182,184,186,188,191,193,195,197,199,202,204,206,209,211,213,215,
    218,220,223,225,227,230,232,235,237,240,242,245,247,250,252,255
};

// Parameter 1 = number of pixels in strip
// Parameter 2 = pin number (most are valid)
// Parameter 3 = pixel type flags, add together as needed:
//   NEO_RGB     Pixels are wired for RGB bitstream
//   NEO_GRB     Pixels are wired for GRB bitstream
//   NEO_KHZ400  400 KHz bitstream (e.g. FLORA pixels)
//   NEO_KHZ800  800 KHz bitstream (e.g. High Density LED strip)
Adafruit_NeoPixel strip = Adafruit_NeoPixel(36, PIN, NEO_GRB + NEO_KHZ800);

//--------------------------------------------------|
//Your NeoPixel rings may not line up with ours, or each other.     |
//Enter which NeoPixel leds are on top LED (0-23 and 0-13).  |
  #define outerTOP_LED                0
  #define innerTOP_LED                1
//--------------------------------------------------|

int outertopLED = outerTOP_LED;
int innertopLED = innerTOP_LED;

//tequila sunrise color scheme
/*
uint32_t milli_color  = strip.Color ( 44,  21,  0); // redest orange
uint32_t second_color = strip.Color (  44,  30, 0); //slightly yellower
uint32_t hour_color   = strip.Color (  44, 42,  0); //yellow
uint32_t minute_color = strip.Color ( 43, 0, 5); //red
uint32_t off_color    = strip.Color (  0,  0,  0);
*/

//blue, green, & purple color scheme

uint32_t milli_color  = strip.Color ( 24,  0,  24); // magenta
uint32_t second_color = strip.Color (  17,  0, 44); // purple
uint32_t hour_color   = strip.Color (  43, 0,  5); // RED for initial no GPS fix
uint32_t minute_color = strip.Color ( 0, 44, 10); // green
uint32_t off_color    = strip.Color (  0,  0,  0);

// Offset hours from gps time (UTC)
//const int offset = 1;   // Central European Time
const int offset = -4;  // Eastern Daylight Time (USA)
//const int offset = -5;  // Central Daylight Time (USA)
//const int offset = -8;  // Pacific Standard Time (USA)
//const int offset = -7;  // Pacific Daylight Time (USA)

/* CLOCK */
class ClockPositions
{
 public:
 
  uint8_t milli;
  uint8_t currentsecond;
  uint8_t currentminute;
  uint8_t currenthour;


  ClockPositions ();
  void update    ();
};


ClockPositions::ClockPositions()
{
  milli         = 0;
  currentsecond = 0;
  currentminute = 0;
  currenthour   = 0;
  //DateTime(__DATE__, __TIME__);
  
}


void ClockPositions::update()
{
  milli  = map ((millis() %  1000), 0,  1000, 0, 24);
  
  currentsecond = outertopLED + map ((second() % 60), 0, 60, 0, 23);
  if (currentsecond > 24) {currentsecond = currentsecond-24;};
  
  currenthour   = innertopLED + map ((hour() % 12), 0,  12, 24, 35);
  if (currenthour > 35) { currenthour = currenthour-12;}
  
  currentminute = outertopLED + map (minute() % 60, 0,  60, 0, 23);
  if (currentminute > 23) {currentminute = currentminute-24;};
}



/* CLOCK VIEW */

class ClockSegments
{
 public:
  ClockPositions    &positions;
  Adafruit_NeoPixel &strip;

  ClockSegments (Adafruit_NeoPixel&, ClockPositions&);
  void draw  ();
  void clear ();
  void add_color (uint8_t position, uint32_t color);
  uint32_t blend (uint32_t color1, uint32_t color2);
};


ClockSegments::ClockSegments (Adafruit_NeoPixel& n_strip, ClockPositions& n_positions): strip (n_strip), positions (n_positions)
{
}


void ClockSegments::draw()
{
  clear();

  add_color (positions.currentminute,  minute_color);
  add_color (positions.currenthour,  hour_color  );
  

  add_color (positions.currentsecond     % 24, second_color);
  add_color ((positions.currentsecond+1) % 24, second_color);
  //add_color ((positions.second+2) % 24, second_color);


  add_color (positions.milli     % 24,  milli_color);
  add_color ((positions.milli+1) % 24,  milli_color);
  add_color ((positions.milli+2) % 24,  milli_color);

  strip.show ();
}


void ClockSegments::add_color (uint8_t position, uint32_t color)
{
  uint32_t blended_color = blend (strip.getPixelColor (position), color);

  /* Gamma mapping */
  uint8_t r,b,g;

  r = (uint8_t)(blended_color >> 16),
  g = (uint8_t)(blended_color >>  8),
  b = (uint8_t)(blended_color >>  0);

  strip.setPixelColor (position, blended_color);
}


uint32_t ClockSegments::blend (uint32_t color1, uint32_t color2)
{
  uint8_t r1,g1,b1;
  uint8_t r2,g2,b2;
  uint8_t r3,g3,b3;

  r1 = (uint8_t)(color1 >> 16),
  g1 = (uint8_t)(color1 >>  8),
  b1 = (uint8_t)(color1 >>  0);

  r2 = (uint8_t)(color2 >> 16),
  g2 = (uint8_t)(color2 >>  8),
  b2 = (uint8_t)(color2 >>  0);


  return strip.Color (constrain (r1+r2, 0, 255), constrain (g1+g2, 0, 255), constrain (b1+b2, 0, 255));
}


void ClockSegments::clear ()
{
  for(uint16_t i=0; i<strip.numPixels (); i++) {
      strip.setPixelColor (i, off_color);
  }
}


/* APP */
ClockPositions positions;
ClockSegments  segments(strip, positions);

void setup ()
{
   // connect at 115200 so we can read the GPS fast enough and echo without dropping chars
  // also spit it out
  Serial.begin(115200);
  Serial.println("Adafruit GPS library basic test!");

  // 9600 NMEA is the default baud rate for Adafruit MTK GPS's- some use 4800
  GPS.begin(9600);
  
  // uncomment this line to turn on RMC (recommended minimum) and GGA (fix data) including altitude
  GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCGGA);
  // uncomment this line to turn on only the "minimum recommended" data
  //GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCONLY);
  // For parsing data, we don't suggest using anything but either RMC only or RMC+GGA since
  // the parser doesn't care about other sentences at this time
  
  // Set the update rate
  GPS.sendCommand(PMTK_SET_NMEA_UPDATE_1HZ);   // 1 Hz update rate
  // For the parsing code to work nicely and have time to sort thru the data, and
  // print it out we don't suggest using anything higher than 1 Hz

  // Request updates on antenna status, comment out to keep quiet
  GPS.sendCommand(PGCMD_ANTENNA);

  useInterrupt(true);

  delay(1000);
  // Ask for firmware version
  Serial1.println(PMTK_Q_RELEASE);
  
  // Request updates on antenna status, comment out to keep quiet
  // GPS.sendCommand(PGCMD_ANTENNA);
    
  strip.begin ();
  strip.show (); // Initialize all pixels to 'off'
}

uint32_t gpsTimer = millis();

void loop ()
{
  // if millis() or timer wraps around, we'll just reset it
  if (gpsTimer > millis()) gpsTimer = millis();
      
  // approximately every 60 seconds or so, update time
  if ((millis() - gpsTimer > 10000)) {
    gpsTimer = millis(); // reset the timer
    
    Serial.print("GPS Fix: ");
    Serial.print((int)GPS.fix);
    Serial.print("  Quality: ");
    Serial.print((int)GPS.fixquality);
    Serial.print("  Satellites: ");
    Serial.println((int)GPS.satellites);
    if (GPS.fix) {
      // set the Time to the latest GPS reading
      setTime(GPS.hour+offset, GPS.minute, GPS.seconds, GPS.day, GPS.month, GPS.year);
      //adjustTime(offset * SECS_PER_HOUR);
      Serial.print("\nTime: ");
      Serial.print(hour(), DEC); Serial.print(':');
      Serial.print(minute(), DEC); Serial.print(':');
      Serial.println(second(), DEC);
      //
      // Set colors for Hours,Minutes,Secs,Milli if we have a GPS fix
      //
      // milli_color  = strip.Color ( 24,  0,  24); // magenta
      // second_color = strip.Color (  17,  0, 44); // purple
      hour_color   = strip.Color (  0, 10,  44); // royal blue
      // minute_color = strip.Color ( 0, 44, 10); // green
    } else {
      //
      // Set colors for Hours,Minutes,Secs,Milli if we DO NOT have a GPS fix
      //
      // milli_color  = strip.Color ( 24,  0,  24); // magenta
      // second_color = strip.Color (  17,  0, 44); // purple
      hour_color   = strip.Color (  43, 0,  5); // royal blue
      // minute_color = strip.Color ( 0, 44, 10); // green
    }
  }

  positions.update ();
  segments.draw ();
 
}

/******************************************************************/
// Interrupt is called once a millisecond, looks for any new GPS data, and stores it
SIGNAL(TIMER0_COMPA_vect) {
  char c = GPS.read();
  // if you want to debug, this is a good time to do it!
  if (GPSECHO)
    if (c) Serial.print(c);
  if (GPS.newNMEAreceived()) {
    //Serial.println(GPS.lastNMEA());   // this also sets the newNMEAreceived() flag to false
  
    if (!GPS.parse(GPS.lastNMEA()))   // this also sets the newNMEAreceived() flag to false
      return;  // we can fail to parse a sentence in which case we should just wait for another
  }
}

void useInterrupt(boolean v) {
  if (v) {
    // Timer0 is already used for millis() - we'll just interrupt somewhere
    // in the middle and call the "Compare A" function above
    OCR0A = 0xAF;
    TIMSK0 |= _BV(OCIE0A);
    usingInterrupt = true;
  } else {
    // do not call the interrupt function COMPA anymore
    TIMSK0 &= ~_BV(OCIE0A);
    usingInterrupt = false;
  }
}

// Fill the dots one after the other with a color
void colorWipe(uint32_t c, uint32_t wait) {
  for(uint16_t i=0; i<strip.numPixels(); i++) {
      strip.setPixelColor(i, c);
      strip.show();
      delay(wait);
  }
}

RogerQ
 
Posts: 14
Joined: Sun Apr 13, 2014 1:45 pm

Re: Flora NeoPixel Ring Clock from the Learning System...

Post by RogerQ »

amazing fixed my problem

User avatar
Doobam
 
Posts: 5
Joined: Tue Sep 23, 2014 10:15 am

Re: Flora NeoPixel Ring Clock from the Learning System...

Post by Doobam »

Does anyone know what the clock should display if not receiving a quality GPS signal. I built mine to spec but all I get is a solid green and flashing red on the Flora and a flashing red on the GPS module. Also, I get no lights at all with the flora unplugged from the USB port. Everything appears to be wired correctly. Thanks for any help.

User avatar
zimbie
 
Posts: 17
Joined: Thu Nov 20, 2014 11:47 pm

Re: Flora NeoPixel Ring Clock from the Learning System...

Post by zimbie »

The code is designed to mark the hours indicator (inner ring) as RED (with the default color scheme, not Tequila Sunrise) when there is no GPS fix. Once there is a GPS fix, the hour indicator changes to BLUE and the time syncs to GPS time (with the defined offset from UTC).

User avatar
makeinspires
 
Posts: 32
Joined: Tue Nov 19, 2013 11:58 pm

Re: Flora NeoPixel Ring Clock from the Learning System...

Post by makeinspires »

Dude, Symo... How did you figure that out? I have had this on my shelf for awhile... Couldn't figure out what to edit.
Best,
Travis

User avatar
zimbie
 
Posts: 17
Joined: Thu Nov 20, 2014 11:47 pm

Re: Flora NeoPixel Ring Clock from the Learning System...

Post by zimbie »

Sets hour color with no fix. This is in the //blue, green, & purple color scheme section towards the beginning of the sketch.
uint32_t hour_color = strip.Color ( 43, 0, 5); // RED for initial no GPS fix

Sets hour color with fix and time. This is in the loop section of the sketch
hour_color = strip.Color ( 0, 10, 44); // royal blue

User avatar
Spetznatz1
 
Posts: 31
Joined: Sun Nov 08, 2015 9:31 pm

Re: Flora NeoPixel Ring Clock from the Learning System...

Post by Spetznatz1 »

I have copied this post from one I started much more recently, but below is a quick quote of the issue I had after using your updated code, (the original code posted with the project didnt work). All I got from the first code was frozen pixels that didn't move, additionally the millisecond sweep wasn't working.

Ok, well it was working great, but for some weird reason the time on the clock suddenly jumped ahead about 5 hours. I looked at the serial monitor and it shows a GPS fix with 7 satellites. The other strange thing is that the serial monitor shows the same time on it as the clock displays. For example the clock shows 13:45 and the time the serial monitor shows per the GPS fix is also 13:45, but the real time should have been 20:45. I checked to make sure the code has the time correct by it showing "const int offset = -4; // Eastern Daylight Time (USA)".
The only way I can display the correct time is to change the location of the NeoPixel LED on the inner ring to compensate for the incorrect time displayed. It just concerns me though that the GPS time is not correct. If it showed the UTC time on the serial monitor I would be satisfied, but its behind by 8 hours. How is that possible? Especially when I am only 4 hours behind UTC?

viewtopic.php?f=41&t=99753&p=500540#p500540

Thanks!

User avatar
windy48
 
Posts: 3
Joined: Sat Nov 26, 2016 4:27 am

Re: Flora NeoPixel Ring Clock from the Learning System...

Post by windy48 »

Amazing design,I believe this will solve many people's problem.

Customized iPad Air/Air 2 Case

Locked
Please be positive and constructive with your questions and comments.

Return to “Clock Kits (discontinued)”