Go Down

Topic: Uno Chrono Interupt (Read 1 time) previous topic - next topic

maxmax39

Hi,
I have got a problem.  Hardware Uno, LCD03 (i2c), 2 buttons, 1 LED

Cabling is ok.  I would like to make a chronometer that start with BP0 (input2) and sop with bp1 (input3).  Everything manage by interuptions.

Code:

#include <MsTimer2.h>
#include <Wire.h>
#define adresseLcd 0x63               //address lcd03

const int LED=4; //led
const int BtStart = 0; // Interrupt 0 pin 2
const int BtStop = 1; // Interrupt 0 pin 3
int Timer1, Timer2, TimerVal = 0;

void setup() 
{
  Serial.begin(9600);
 
  pinMode(LED, OUTPUT);
  MsTimer2::set(1000, InterruptTimer2); // 1000ms
  MsTimer2::start(); // active Timer 2

  attachInterrupt(BtStart, vStart, RISING);
  attachInterrupt(BtStop, vStop, RISING);
  Wire.begin();
  Wire.beginTransmission(addressLcd);
  Wire.write((byte)(0x00)); //null
  Wire.write((byte)(0x01)); //go home
  Wire.write((byte)(0x13)); //turn on backlight
  Wire.write((byte)(0x0C)); //clear screen
  Wire.write("Wait...");
  Wire.endTransmission();
//Wait still show
}
void loop(){

}
void write2i2c ( )
{
  Serial.println("First");
  //Wire.begin();
  Wire.beginTransmission(adDressLcd);
  Wire.write((byte)(0x00)); //null
  Wire.write((byte)(0x01)); //go home
  //Wire.write((byte)(0x0C)); //clear screen
  Wire.write("First");
  Wire.endTransmission();
 
}

void InterruptTimer2() { // interupt Timer2
  digitalWrite(LED, HIGH);
  delayMicroseconds(10000);
  digitalWrite(LED, LOW);
  TimerVal +=1;
  Serial.println(TimerVal); //I could see values in COM

}

void vStart()
{
  TimerVal =0;
  write2i2c();
}
void vStop()
{
  Timer1 = TimerVal;
  Serial.println(Timer1);
}

But when I pushed on BP0, the program stop.  Where is the problème. I have to stop interupt during i2c??

Thanks
Maxmax

dc42


Everything manage by interuptions.


That's your mistake, you are trying to do too much in the interrupt service routines. You should do the minimum amount of work necessary in ISRs. In your case, this is probably to read the current time and store it when you press the start button, and do the same again (using a different variable) when you press the stop button. You must never call delay or Serial.print etc. from an ISR.
Formal verification of safety-critical software, software development, and electronic design and prototyping. See http://www.eschertech.com. Please do not ask for unpaid help via PM, use the forum.

maxmax39

Ok,
serial is just there for debuging.  But I want to write on lcd.
Have you got an idea to make a chrono with a precision of 0.1s

Thanks a lot

Max

dc42

A precision of 0.1s over what time interval? 1 minute? 1 year?
Formal verification of safety-critical software, software development, and electronic design and prototyping. See http://www.eschertech.com. Please do not ask for unpaid help via PM, use the forum.


PaulS

Code: [Select]
  MsTimer2::start(); // active Timer 2
You said you wanted the timer to start when there was an interrupt on pin 2. So, why are you starting it here?

Writing to the I2C device requires that interrupts be enabled. They are disabled during an interrupt service routine, like vStart().

maxmax39

I started the to only count, when I push on bp0 I reset a counter that increment with the interrupt.

dc42


1 to 5 minutes


0.1sec in 5 min = 0.1sec in 300sec = 1 part in 3000, i.e. 0.033% or 330ppm. Unfortunately, the ceramic resonator used on the Uno has a tolerance of only 0.5%. To get the accuracy you want, you need an Arduino that uses a crystal, such as a Leonardo, or alternatively make your own barebones system.

Here is an outline of the sort of code you need:

Code: [Select]

volatile bool running = false;
volatile unsigned long startTime, stopTime;

void setup()
{
  // set up pin modes, input pullups, button interrupts, and initialize LCD
}

void startButtonIsr()
{
   startTime = micros();
   running = true;
}

void stopButtonIsr()
{
   stopTime = micros();
   running =false;
}

void loop()
{
  while (!running) { }  // wait until started
  while (running) { }   // wait until stopped
  unsigned long runTime = (stopTime - startTime)/100000UL;  //calculate running time in units of 0.1 second
  lcd.clear(); 
  lcd.print(runTime/10);
  lcd.write('.');
  lcd.print(runTime%10);
}
Formal verification of safety-critical software, software development, and electronic design and prototyping. See http://www.eschertech.com. Please do not ask for unpaid help via PM, use the forum.

dhenry

You shouldn't do any serial / i2c / delay in the interrupt - they are too slow.

I would do this instead:

Code: [Select]

void loop(){
  if (disp_flag) {
    disp_flag = 0; //reset disp_flag
    write2i2c(); //display the message
  }

}
void write2i2c ( )
{
  Serial.print("TimerVal = "); Serial.print(Timer1); Serial.print(" seconds.\r\n");
  //Wire.begin();
#if 0
  Wire.beginTransmission(adDressLcd);
  Wire.write((byte)(0x00)); //null
  Wire.write((byte)(0x01)); //go home
  //Wire.write((byte)(0x0C)); //clear screen
  Wire.write("First");
  Wire.endTransmission();
#endif 
}

void InterruptTimer2() { // interupt Timer2
  digitalWrite(LED, HIGH);
  //delayMicroseconds(10000);
  digitalWrite(LED, LOW);
  TimerVal +=1;
  //Serial.println(TimerVal); //I could see values in COM

}

void vStart()
{
  TimerVal =0; //reset TimerVal
  //write2i2c();
}
void vStop()
{
  Timer1 = TimerVal; //save TimerVal
  //Serial.println(Timer1);
  disp_flag = 1; //set the flag
}


You will also need to enable interrupts in your setup().

maxmax39

I saw that I can t use interrupt in an interrupt
now I use flag and put them 1 or 0
with that it's better, and I can use interrupt to count time

Go Up