Attiny85 : problem with stSequence and int value (too high , memory issue ?)

Hello all,

I am working on a project which make leds blinking, based on a scenario. Attiny85 used.
I’ve created a stSequence which works nice, but I have some issues depending on the duration of the sequence.

Below, you can see a 1mn, 2mn and 6mn program.
During that program, the leds are turned on progressively, then blink 4 times.

1mn and 2mn works fine but not 6mn. That makes me think that “tempsprog” is getting a too high value, and the Attiny85 does not work properly.

During the 6mn program, the leds are turned on progressively, but do not blink. They stay ON until I power off the board…

int fadeAmount = 1;
int puissance =0;
int ledPin =0;
int tempsprog = 0;
unsigned long time_now = 0;


typedef struct
{
  int initA;
  int delay1;      //temps en ms pour atteindre
  int target1;
  int delay2;
  int montee;

} ST_SEQUENCE;


void setup() {
  
pinMode(ledPin, OUTPUT);

}


void(* resetFunc) (void) = 0;


void arret()
{
  delay(1000);
  resetFunc();
}



void loop() {

//analogWrite(ledPin, 190);

if(digitalRead(A1)==HIGH) //1 mn
{
  tempsprog=4600+(7500*1); //(ajouter 7500*nbminutes supplémentaires : exemple --> 1 mn = 4700 ; 2 mn = 4700 + 7500; 20 mn = 4700 + 19*7500))
  puissance=190;
  scenario2();

}

if(digitalRead(A2)==HIGH) //2 mn
{
    tempsprog=4600+(7500*2); 
  puissance=190;
  scenario2();

}

if(digitalRead(A3)==HIGH) //6 mn
{
    tempsprog=4600+(7500*6); 
  puissance=190;
  scenario2();

}

  delay(10);
  
}

void scenario2()  {

delay(500);

ST_SEQUENCE stSequence[] = {
    {10, 1000, puissance, 0,20}
  , {puissance, tempsprog, puissance, tempsprog,0} // Starting scenario
  , {0, 500, puissance, 500,0}
  , {0, 500, puissance, 500,0}
  , {0, 500, puissance, 500,0}
  , {0, 500, puissance, 500,0}
  , {puissance, tempsprog, puissance, tempsprog,0}
  , {0, 500, puissance, 500,0}
  , {0, 500, puissance, 500,0}
  , {0, 500, puissance, 500,0}
  , {0, 500, puissance, 500,0}
  , {puissance, tempsprog, puissance, tempsprog,0}
  , {0, 500, puissance, 500,0}
  , {0, 500, puissance, 500,0}
  , {0, 500, puissance, 500,0}
  , {0, 500, puissance, 500,0}
  , {puissance, tempsprog, puissance, tempsprog,0}
  , {0, 500, puissance, 500,0}
  , {0, 500, puissance, 500,0}
  , {0, 500, puissance, 500,0}
  , {0, 500, puissance, 500,0}

};
   
    for(int i = 0 ; i < sizeof(stSequence)/sizeof(stSequence[0]); i++)
  {
    time_now = 0;
    analogWrite(ledPin, stSequence[i].initA);

    while (time_now < stSequence[i].delay1) 
    {
  
    time_now++;
    delay(1);
    if (digitalRead(A1)==HIGH || digitalRead(A2)==HIGH || digitalRead(A3)==HIGH) {
    analogWrite(ledPin, 0);
    arret();
    }
    }

    while(fadeAmount < stSequence[i].target1-stSequence[i].initA){
    
    fadeAmount++;
     analogWrite(ledPin, stSequence[i].initA+fadeAmount);
    time_now = 0;
    while (time_now < stSequence[i].montee) 
    {
  
    time_now++;
    delay(1);
    if (digitalRead(A1)==HIGH || digitalRead(A2)==HIGH || digitalRead(A3)==HIGH) {
    analogWrite(ledPin, 0);
    arret();
    }
    }
    }
    
    fadeAmount=0;
        time_now = 0;
    while (time_now < stSequence[i].delay2) 
    {
  
    time_now++;
    delay(1);
    if (digitalRead(A1)==HIGH || digitalRead(A2)==HIGH || digitalRead(A3)==HIGH) {
    analogWrite(ledPin, 0);
    arret();
    }
    }
    
  }

  tempsprog=0;
 

 analogWrite(ledPin, 0);

}

The int data type is a 16 bit data type (in 8 bit Arduino land) that can hold numbers from -32768 to 32767. The tempsprog variable is an int so

 tempsprog=4600+(7500*6);

will cause roll over.

Arduino data types and the ranges of numbers that each will hold.

Using the IDE autoformat tool (ctrl-t or Tools, Auto Format) will make your code easier to follow.

Hello !

Thank you for the fast reply. I also tried "long" instead of "int" as variable and didn't work.
Any suggestion for the best variable to use ?

Kindly

Data types used for timing (delay etc) should not be signed since negative delay or "back in time" is impossible (unless you watch BTTF or listen to Huey Lewis, LOL). You should change some of your "int" data types to "unsigned long" or "uint32_t":

...
uint32_t tempsprog = 0;
...
typedef struct
{
  ...
  uint32_t delay1;
  ...
  uint32_t delay2;
  ...

} ST_SEQUENCE;

Thank you very much for your help, unfortunately their is no change…

I’ve changed “int” to “uint32_”, but same result. Only 1mn and 2mn are working properly.
When “tempsprog = 4600 + (7500 * 6);”, the program does not work properly.

Very strange to me …

uint32_t fadeAmount = 1;
uint32_t puissance = 0;
int ledPin = 0;
uint32_t tempsprog = 0;
uint32_t time_now = 0;


typedef struct
{
  uint32_t initA;
  uint32_t delay1;      //temps en ms pour atteindre
  uint32_t target1;
  uint32_t delay2;
  uint32_t montee;

} ST_SEQUENCE;


void setup() {

  pinMode(ledPin, OUTPUT);

}


void(* resetFunc) (void) = 0;


void arret()
{
  delay(1000);
  resetFunc();
}



void loop() {

  //analogWrite(ledPin, 190);

  if (digitalRead(A1) == HIGH) //1 mn
  {
    tempsprog = 4600 + (7500 * 1); //(ajouter 7500*nbminutes supplémentaires : exemple --> 1 mn = 4700 ; 2 mn = 4700 + 7500; 20 mn = 4700 + 19*7500))
    // tempsprog=100000;
    puissance = 138;
    scenario2();

  }

  if (digitalRead(A2) == HIGH) //2 mn
  {
    tempsprog = 4600 + (7500 * 2);
    //  tempsprog=4000000;
    puissance = 138;
    scenario2();

  }

  if (digitalRead(A3) == HIGH) //3 mn
  {
    tempsprog = 4600 + (7500 * 6);
    // tempsprog=50000;
    puissance = 138;
    scenario2();

  }

  delay(10);

}

void scenario2()  {

  delay(500);

  ST_SEQUENCE stSequence[] = {
    {10, 1000, puissance, 0, 20}
    , {puissance, tempsprog, puissance, tempsprog, 0} // Starting scenario
    , {0, 500, puissance, 500, 0}
    , {0, 500, puissance, 500, 0}
    , {0, 500, puissance, 500, 0}
    , {0, 500, puissance, 500, 0}
    , {puissance, tempsprog, puissance, tempsprog, 0}
    , {0, 500, puissance, 500, 0}
    , {0, 500, puissance, 500, 0}
    , {0, 500, puissance, 500, 0}
    , {0, 500, puissance, 500, 0}
    , {puissance, tempsprog, puissance, tempsprog, 0}
    , {0, 500, puissance, 500, 0}
    , {0, 500, puissance, 500, 0}
    , {0, 500, puissance, 500, 0}
    , {0, 500, puissance, 500, 0}
    , {puissance, tempsprog, puissance, tempsprog, 0}
    , {0, 500, puissance, 500, 0}
    , {0, 500, puissance, 500, 0}
    , {0, 500, puissance, 500, 0}
    , {0, 500, puissance, 500, 0}

  };

  for (uint32_t i = 0 ; i < sizeof(stSequence) / sizeof(stSequence[0]); i++)
  {
    time_now = 0;
    analogWrite(ledPin, stSequence[i].initA);

    while (time_now < stSequence[i].delay1)
    {

      time_now++;
      delay(1);
      if (digitalRead(A1) == HIGH || digitalRead(A2) == HIGH || digitalRead(A3) == HIGH) {
        analogWrite(ledPin, 0);
        arret();
      }
    }

    while (fadeAmount < stSequence[i].target1 - stSequence[i].initA) {

      fadeAmount++;
      analogWrite(ledPin, stSequence[i].initA + fadeAmount);
      time_now = 0;
      while (time_now < stSequence[i].montee)
      {

        time_now++;
        delay(1);
        if (digitalRead(A1) == HIGH || digitalRead(A2) == HIGH || digitalRead(A3) == HIGH) {
          analogWrite(ledPin, 0);
          arret();
        }
      }
    }

    fadeAmount = 0;
    time_now = 0;
    while (time_now < stSequence[i].delay2)
    {

      time_now++;
      delay(1);
      if (digitalRead(A1) == HIGH || digitalRead(A2) == HIGH || digitalRead(A3) == HIGH) {
        analogWrite(ledPin, 0);
        arret();
      }
    }

  }

  tempsprog = 0;


  analogWrite(ledPin, 0);

}

What is attached to A1, A2 and A3? Can you provide a wiring diagram or a picture of the wiring?

Your code seems overcomplicated and the array of struct's is IMHO not necessary. Using a counter in combination with "delay(1)" as timing is inaccurate and not recommended. Using a device-reset as part of the program flow does not seem proper either.

Hello,

A1, A2 and A3 are simply connected to 3 push buttons. What I wanted to do is :

  • Program is waiting for a button behing pressed
  • Depending on which push button pressed, start a program with a specific duration.
  • If a button is pressed when the program is started, stop it (then if a button is pressed again, restart the program).

This is what the stSequence is supposed to do. I can modify the duration of each step, and the power (0-255). A better solution may be usefull .....

The program will light a led at the output, at a specific power (0-255).
Below image shows the program structure. Only the duration changes between the 3 programs.

tempsprog = 4600 + (7500 * 6); 7500*6 = 45000, this multiplication is happening in signed 16-bit standard (INT) unless differently specifeid.
change it to4600 + (7500UL * 6); and it should work properly.

I really cannot see how the posted code should remotely produce the result you want from it. Your "ledPin" is pin 0 which is the serial RX pin, don't use the TX/RX pins for anything else than serial communication. Your buttons are wired to analog inputs and on some variants of arduino, you cannot use "digitalRead" on the analog pins - and you have not selected a "pinMode" for them either.

IMHO your sketch and wiring is something to forget all about. You need to read up on how to create a state machine since this is the sollution and then start over with one, correctly wired button + LED and work your way up from there.

EDIT: Brain fart!

The solution provided by Deva_Rishi is working perfectly. Thank you very much for your help, Danois90 and Deva.

I need to clean my code anyway.

pin 0 which is the serial RX pin,

Tiny85 has no hardware serial.

groundFungus:
Tiny85 has no hardware serial.

Sorry, my bad! :slight_smile: