array overshooting

I need to add an offset to where i call my array index in this example +6, i have an interrupt set up that creates a counter which ranges from 0-255, but i also have an if statement which will reset the counter to 0 upon it being equal to 255, i then use this counter to read the index of my array, however when i read it with counter=counter the numbers are smooth but when i add an offset of +6 to the second time i read the table i get a flicker, i think this is down to the counter over shooting 255 and thus looking at the array for an integer which doesn’t exist, how would i read the array table 6 points further down without overshooting my 255, i can obviously do it with a lot of if statements but i will eventually require 40 offsets and 40 different readings so it doesn’t seem very economical.

This is being used to control DMX lighting and so i can see the obvious number flicker/overshoot.

hope this makes sense to someone

// Arduino timer CTC interrupt example
//
// avr-libc library includes
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <DmxMaster.h>


// sine lookup table stored in the flash memory
PROGMEM prog_uchar sinetable[256] = {
  128,131,134,137,140,143,146,149,152,156,159,162,165,168,171,174,
  176,179,182,185,188,191,193,196,199,201,204,206,209,211,213,216,
  218,220,222,224,226,228,230,232,234,236,237,239,240,242,243,245,
  246,247,248,249,250,251,252,252,253,254,254,255,255,255,255,255,
  255,255,255,255,255,255,254,254,253,252,252,251,250,249,248,247,
  246,245,243,242,240,239,237,236,234,232,230,228,226,224,222,220,
  218,216,213,211,209,206,204,201,199,196,193,191,188,185,182,179,
  176,174,171,168,165,162,159,156,152,149,146,143,140,137,134,131,
  128,124,121,118,115,112,109,106,103,99, 96, 93, 90, 87, 84, 81, 
  79, 76, 73, 70, 67, 64, 62, 59, 56, 54, 51, 49, 46, 44, 42, 39, 
  37, 35, 33, 31, 29, 27, 25, 23, 21, 19, 18, 16, 15, 13, 12, 10, 
  9,  8,  7,  6,  5,  4,  3,  3,  2,  1,  1,  0,  0,  0,  0,  0,  
  0,  0,  0,  0,  0,  0,  1,  1,  2,  3,  3,  4,  5,  6,  7,  8,  
  9,  10, 12, 13, 15, 16, 18, 19, 21, 23, 25, 27, 29, 31, 33, 35, 
  37, 39, 42, 44, 46, 49, 51, 54, 56, 59, 62, 64, 67, 70, 73, 76, 
  79, 81, 84, 87, 90, 93, 96, 99, 103,106,109,112,115,118,121,124
};


int count;
int offset = 6;


int speeder = 100; // speed of counter

int dmx_value1;
int dmx_value2;
int dmx_value3;
int dmx_value4;
int dmx_value5;
int dmx_value6;

void setup()
{
  Serial.begin(9600);

// initialize Timer1
cli();          // disable global interrupts
TCCR1A = 0;     // set entire TCCR1A register to 0
TCCR1B = 0;     // same for TCCR1B

// set compare match register to desired timer count:
//OCR1A = 15624; Original speed control
OCR1A = speeder; 

// turn on CTC mode:
TCCR1B |= (1 << WGM12);

// Set CS10 and CS12 bits for 1024 prescaler:
TCCR1B |= (1 << CS10);
TCCR1B |= (1 << CS12);

// enable timer compare interrupt:
TIMSK1 |= (1 << OCIE1A);

// enable global interrupts:
sei();
}




void loop()
{
  DmxMaster.write(1,0);  //Red
  DmxMaster.write(2,0);  //Green
  DmxMaster.write(3,255);  //Blue
  DmxMaster.write(4, dmx_value1);        //Dimmer
  DmxMaster.write(5, 0);          //Shutter
  
  DmxMaster.write(6,255);  //Red
  DmxMaster.write(7,0);  //Green
  DmxMaster.write(8,255);  //Blue
  DmxMaster.write(9, dmx_value2);        //Dimmer
  DmxMaster.write(10, 0);         //Shutter
  
  
  Serial.print("V1=");
  Serial.println(count);
  Serial.print("V2=");
  Serial.println(count);


 /* Serial.print("V3=");
  Serial.println(dmx_value3);
  Serial.print("V4=");
  Serial.println(dmx_value4);
  Serial.print("V5=");
  Serial.println(dmx_value5);
  Serial.print("V6=");
  Serial.println(dmx_value6);
  delay(50);
  */
}

ISR(TIMER1_COMPA_vect)
{

  if (count == 255){  //***********If this number is changed to say 240 the flicker no longer occurs
    count = 0;
  }
  
  else{
    count ++;
  }
  
dmx();

  }   

void dmx(){
  dmx_value1 = (pgm_read_byte_near (&sinetable[(count)]));
  dmx_value2 = (pgm_read_byte_near (&sinetable[(count+offset)]));
}

Can't you just AND your index with 255?

I had to test this first. Change data type of count and offset to byte, and override the data type in the index where the two values are added.

byte count = 0;
byte offset = 6;

  dmx_value2 = (pgm_read_byte_near (&sinetable[(byte)(count+offset)]));

Does that work for you?

if you don’t put the sine table in PROGMEM but in RAM does that help ?

Can't you just AND your index with 255?

As AWOL says, because your array is one of the magic sizes (IE a power of 2) you can simply AND the counter to reset it.

if (count == 255)

You should test for >=, if you are incrementing by 6 the values will be either 252 or 258, never 255. 240 works because it happens to be a multiple of 6.


Rob

Don't need an AND. Don't need a comparison. Here is my test code:

byte count = 0;
byte offset = 6;

void setup() {
  Serial.begin(115200);
}

void loop() {
  Serial.print("Count: ");
  Serial.print(count);
  Serial.print(" + offset: ");
  Serial.println((byte)(count + offset));
  count++;
  delay(100);
}

surfer tim's solution seems to have worked,

  dmx_value2 = (pgm_read_byte_near (&sinetable[(byte)(count+offset)]));

although i'm curious as to why adding byte has stopped it overshooting the array?

and thanks graynomad, as you say i should of had it checking

=255 not just ==255

thanks

i'm curious as to why adding byte has stopped it overshooting the array?

You had an int, that's 16 bits (signed) so it would count up to 32k. Changing it to a byte (unsigned char) which is only 8 bits forced a wrap around at 256.


Rob

Thanks for answering that, Graynomad! Nice hat. :wink:

And besides it working, if you use a modified version of the code I posted in reply #5, it is faster and uses less memory, both program and SRAM.

OK I've not studied your sketch thoroughly but I notice you have

void dmx(){
  dmx_value1 = (pgm_read_byte_near (&sinetable[(count)]));
  dmx_value2 = (pgm_read_byte_near (&sinetable[(count+offset)]));
}

So surely to avoid "overshoot" you want count +offset to be less than 256;

so in your ISR(TIMER1_COMPA_vect) function
if (count == 255)
Should actually read
if ((count+offset) == 255)

@KenF: This takes care of that. Note the addition of the byte data type override in the array index.

  dmx_value2 = (pgm_read_byte_near (&sinetable[(byte)(count+offset)]));

SurferTim:
@KenF: This takes care of that. Note the addition of the byte data type override in the array index.

  dmx_value2 = (pgm_read_byte_near (&sinetable[(byte)(count+offset)]));

Does that actually work?
I see no reason why it shouldn't, it's just not a situation where I'd use such a method.
I'd feel more comfortable with

dmx_value2 = (pgm_read_byte_near (&sinetable[(count+offset)%256]));

Does that actually work?

Yes. Run the test code in reply #5.

Why add instructions that are not needed? The byte override does the %256 for you without doing the maths.