Need delay in loop() to work with timer interrupt Mega ADK

Hi,

I’m reading encoder values from a dc motor control board and I got it working but I need some kind of delay in my loop function and I don’t understand why.

I have maked the delay in the code below with **** HERE ****. I can use delay(0) and also send something on the serial port and it works but if I remove the delay(0) it hangs and never enters the if statement if(trigger == 1).

I read the encoder values from I2C bus and communicates with host (windows) with serial (USB). It seems like it doesn’t enter the ISR when I don’t have the delay, but I’m not sure.

If anyone has an idea what the issue can be, please let me know.

// 
#include "Wire.h"

#define ledPin 13
#define startStopButton 26 // Internal pull-up resistor, 1 - stop, 0 - run 
#define motorBoardAddress 0x58 // 0xB0 shited to the right

// Registers
#define REG_RW_SPEED          0
#define REG_RW_TURN           1
#define REG_R_ENC1A           2
#define REG_R_ENC1B           3
#define REG_R_ENC1C           4
#define REG_R_ENC1D           5
#define REG_R_ENC2A           6
#define REG_R_ENC2B           7
#define REG_R_ENC2C           8
#define REG_R_ENC2D           9
#define REG_R_BATT           10
#define REG_R_MOTOR1_CURRENT 11
#define REG_R_MOTOR2_CURRENT 12
#define REG_R_REVISION       13
#define REG_RW_ACC_RATE      14
#define REG_RW_MODE          15
#define REG_RW_COMMAND       16

#define RUN_TIME 700

static int counter = 0;
static unsigned char trigger = 0;
static unsigned int overrun = 0;
static unsigned char done = 0;
static unsigned char sent = 0;
static unsigned char log_buffer[7000];
static int cnt = 0;
static int all_counter = 0;
static int read_cnt = 0;

void setup()
{
    pinMode(ledPin, OUTPUT);
    pinMode(startStopButton, INPUT);
    digitalWrite(startStopButton, HIGH);
  
    // Start I2C bus
    Wire.begin();
  
    // Start serial bus to host
    Serial.begin(9600);
  
    // initialize timer1 
    noInterrupts();           // disable all interrupts
    TCCR1A = 0;
    TCCR1B = 0;
    TCNT1  = 0;

    OCR1A = 625;//625;              // compare match register 16MHz/256/100Hz (10ms)
    TCCR1B |= (1 << WGM12);   // CTC mode
    TCCR1B |= (1 << CS12);    // 256 prescaler 
    TIMSK1 |= (1 << OCIE1A);  // enable timer compare interrupt
    interrupts();             // enable all interrupts
}

ISR(TIMER1_COMPA_vect)          // timer compare interrupt service routine 10 ms
{
    unsigned char inb;

    // Check for overrun
    if (trigger != 0)
    {
        overrun++;
    }
    
    all_counter++;
      
    // Read button
    inb = digitalRead(startStopButton);
 
    if ((inb == 0) && (done == 0)) 
    //if (done == 0)
    {
        counter++;
        trigger = 1;
        digitalWrite(ledPin, 1);
    }
    else
    {
        //counter = -1;
        trigger = 0;
        digitalWrite(ledPin, 0);
    }
}

void loop()
{
  int idx;
  unsigned char batt;
  
  Serial.println("*** Drive Step Test Program ***");
  Serial.print("--->Initializing...");
  
  // Set mode to 2, speed and turn
  Wire.beginTransmission(motorBoardAddress);
  Wire.write(REG_RW_MODE);
  Wire.write(2);
  Wire.endTransmission();
  
  // Zero encoder counters
  Wire.beginTransmission(motorBoardAddress);
  Wire.write(REG_RW_COMMAND);
  Wire.write(32);
  Wire.endTransmission();
  
  Serial.println("Done!");
  
  Wire.beginTransmission(motorBoardAddress);
  Wire.write(REG_R_BATT); 
  Wire.endTransmission();
  
  Wire.beginTransmission(motorBoardAddress);
  Wire.requestFrom(motorBoardAddress, 1);
  batt = Wire.read();
  Wire.endTransmission(); 
  
  Serial.print("Battery voltage: ");
  Serial.println(batt);
  
  
    while(done == 0)
    {
        delay(0);//Serial.println("while");   // ********* HERE ***********
        if (trigger == 1)
        {
            //Serial.println("trigg");
            if (counter <= RUN_TIME)
            {
                read_dc_regs_to_buffer();
                read_cnt++;
            } 
            else
            {
                done = 1;
            }
            trigger = 0;
        }
    }
  
    if (overrun > 0)
    {
        Serial.print("Overruns: ");
        Serial.println(overrun); 
    }
    Serial.println("DONE! - Sending data:");
    for(idx=0;idx < (RUN_TIME * 9); idx++)
    {
         Serial.println(log_buffer[idx]);
    }
    Serial.print("Counter: ");
    Serial.println(counter);
    Serial.print("cnt: ");
    Serial.println(cnt);
    Serial.print("idx: ");
    Serial.println(idx);
    Serial.print("all_counter: ");
    Serial.println(all_counter);
    Serial.print("read_cnt: ");
    Serial.println(read_cnt);
 
    for(;;)
    {
         delay(100); 
    }
  
  
  /*
 
  Wire.beginTransmission(motorBoardAddress);
  Wire.write(0);
  Wire.write(128);
  Wire.endTransmission();
  
  Wire.beginTransmission(motorBoardAddress);
  Wire.write(1);
  Wire.write(128);
  Wire.endTransmission();
  */
}

void read_dc_regs_to_buffer() 
{
    int idx;
    
    Wire.beginTransmission(motorBoardAddress);
    Wire.write(REG_R_ENC1A); 
    Wire.endTransmission();
  
    Wire.beginTransmission(motorBoardAddress);
    Wire.requestFrom(motorBoardAddress, 8);
    for(idx=0; idx < 8; idx++) 
    {    
        log_buffer[cnt] = Wire.read();
        cnt++;
    }
    log_buffer[cnt] = 222;
    cnt++;
    Wire.endTransmission(); 
}

Let's clean up a few things:


  • The variable "done" is shared between an ISR and main code. It should be declared volatile. Ditto for "trigger" and possibly others.

  • In this code:
  Wire.beginTransmission(motorBoardAddress);
  Wire.requestFrom(motorBoardAddress, 1);
  batt = Wire.read();
  Wire.endTransmission();

You don't put beginTransmission() and endTransmission() around requestFrom(). See:


  • Huh?
 for(;;)
  {
    delay(100); 
  }

What does the delay achieve?


  OCR1A = 625;//625;              // compare match register 16MHz/256/100Hz (10ms)

Timer count registers are zero-relative so it should be 624.

What does the delay achieve?

Obviously, it makes the infinite loop take longer to complete. Any one can see that. I'm surprised you need to ask.

Ach, I stand corrected! :stuck_out_tongue:

Ok, I made the changes but I have to wait until next week to test it as I burned the motor control board.

I removed a lot of code before submitting and the delay is left from that.

Thanks!