Go Down

Topic: Code works on Uno, but doesn't function properly on Attiny85 (Read 88 times) previous topic - next topic

slonimer

Hey,

So I've written some code to use Neopixels to create a clock.  It takes inputs from 2 push buttons to set the hours and minutes.  It checks the inputs from these using functions, checkMinute() and checkHour().

The full code is too long to display here, so I've just included the setup, loop, and checkMinute and checkHour functions below.  The full code is attached.

Code: [Select]
#include <Adafruit_NeoPixel.h>

#define PIN 0

...

void setup()  {
  //Only necessary for serial monitor.  Will commments out for final
  // Serial.begin(9600);
  strip.begin();
  strip.show(); // Initialize all pixels to 'off'
  //
  pinMode(hourPin,INPUT);
  pinMode(minutePin,INPUT);   
}

void loop(){
  //Idea: Every 30 min and every hour, put on a little light show!
  //Idea: Automatically turn to be less bright/off during the day time.
  // Actually, in the day,brightly blink just the Minutes and Hours for 3 seconds every minute

  // Check what the minute and hours are and if they've changed
  hours_old = hours;
  minutes_old = minutes;
  seconds_old = seconds;

  time_since_start = millis();
  time_diff = reference_time + time_since_start - time_changed;

  //NOTE: If testing, should set toggleValue1 and toggleValue2
  //within checkMinute and checkHour to 0, because if they're just floating
  // ie not HIGH or LOW, will just result in reference time going totally nuts!
   
  //Serial.println(reference_time);
  //Serial.println(time_diff);
 
  //NOTE: DECIMALS GET ALL MESSED UP WITH ARDUINO AND LARGE NUMBERS.
  // Do NOT divide milliseconds by 1000 to get into seconds.  Just deal
  // with the math on the millisecond scale.
  time_diff = time_diff % (86400000);
  hours = floor(time_diff/(3600000));
  minutes = floor( (time_diff - (hours*3600000))/(60000) );
  seconds = (time_diff - (hours*3600000) - (minutes*60000) ) / 1000;
  //Can't do as below.  The extra math fucks it all up.
//  time_diff = time_diff % (86400*1000);
//  hours = floor(time_diff/(3600*1000));
//  minutes = floor( (time_diff - (hours*3600*1000))/(60*1000) );
//  seconds = (time_diff - (hours*3600*1000) - (minutes*60*1000) ) / 1000;

  seconds = seconds % 60;
 
//  Serial.print(hours);
//  Serial.print(":");
//  Serial.print(minutes);
//  Serial.print(":");
//  Serial.println(seconds);

  // Check the manual inputs to see if should increment time
  checkHour();
  checkMinute();

  //Set the Pixel values and colors
  setHoursPixels();
  setMinutesPixels();
  setSecondsPixels();
 
  //Show the new pixel configuration
  for(int i=0; i<strip.numPixels(); i++){
       strip.setPixelColor(i,strip.Color(pixelR[i]*n, pixelG[i]*n, pixelB[i]*n));
    }
  strip.show();
}



void checkHour(){
//Check the Hour Inputs
   //toggleValue1 = 0;
   toggleValue1 = digitalRead(hourPin);
   if ((millis() - time_changed) > debounceDelay) {
     if (toggleValue1!=old_toggleValue1){
       hours_set = hours;
       hours_set++;
       if (hours>23){
         hours=0;
       }
       //Update the reference time - minimize multiplication steps to avoid errors
       reference_time = (minutes_set*60000 + hours_set*3600000);
       //reference_time  =  (minutes_set*60 + hours_set*3600)*1000;
       //Make note of when the time was altered:
       time_changed = millis();
     }
   }
 old_toggleValue1 = toggleValue1;
}


void checkMinute(){
//Check the Minute inputs
   //toggleValue2 = 0;
   toggleValue2 = digitalRead(minutePin);
  if ((millis() - time_changed) > debounceDelay) {
    if (toggleValue2!=old_toggleValue2){
      minutes_set = minutes;
      minutes_set++;
      if (minutes_set>59){
        minutes_set=0;
      }
      //Update the reference time - minimize multiplication steps to avoid errors
      reference_time = (minutes_set*60000 + hours_set*3600000);
      //reference_time  =  (minutes_set*60 + hours_set*3600)*1000;
      //Make note of when the time was altered:
      time_changed = millis();
    }
  }
 old_toggleValue2 = toggleValue2;
}

...




I've successfully uploaded it to an Uno, and had it work just fine.  When I try to upload it onto an Attiny85 (using a pro-mini at the ISP), it uploads to the attiny with no errors, but there is no output from Pin0 which should be sending Data to the neopixels.  I've done some tests and am quite confident the problem is with the code and not with the wiring.  I find that if I comment out either the checkMinute() or checkHour() function, it does work.  The pixels that indicate seconds, minutes, and hours all light up and move to indicate the time.  But I'm only able to set the Hours or the Minutes, but not both.  However, if neither of the 2 are commented it just doesn't work!

I'm completely stumped.  I know that Attiny's can be a bit weird sometimes, but this makes no sense to me.

Thanks so so so much for any help!

Hackscribble

Hi slonimer

Possibly running out of SRAM?  Attiny86 has 512 bytes vs 2KB on a Uno.

As a test, can you reduce the number of pixels?  This would save 2 bytes per pixel in the memory that the neopixel library uses, plus 3 bytes per pixel from your boolean arrays (I believe booleans are stored as 1 byte per element).

Regards

Ray
Hackscribble.  Writing about making things.
arduino@hackscribble.com | www.hackscribble.com

slonimer

Yes!  That works!  I changed the number of neopixels from 48 to 47 (which was unnecessarily high), since I only actually had 47.  And it works!  It was just barely running out of memory, and by reducing by one neopixel I save 24 bytes.

Thanks so so so much!

Go Up