Pages: [1]   Go Down
Author Topic: Uno Chrono Interupt  (Read 764 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Jr. Member
**
Karma: 0
Posts: 77
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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
Logged

United Kingdom
Offline Offline
Tesla Member
***
Karma: 220
Posts: 6587
Hofstadter's Law: It always takes longer than you expect, even when you take into account Hofstadter's Law.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
Logged

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.

Offline Offline
Jr. Member
**
Karma: 0
Posts: 77
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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
Logged

United Kingdom
Offline Offline
Tesla Member
***
Karma: 220
Posts: 6587
Hofstadter's Law: It always takes longer than you expect, even when you take into account Hofstadter's Law.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

A precision of 0.1s over what time interval? 1 minute? 1 year?
Logged

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.

Offline Offline
Jr. Member
**
Karma: 0
Posts: 77
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

1 to 5 minutes

Logged

Seattle, WA USA
Online Online
Brattain Member
*****
Karma: 548
Posts: 46032
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
  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().
Logged

Offline Offline
Jr. Member
**
Karma: 0
Posts: 77
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

United Kingdom
Offline Offline
Tesla Member
***
Karma: 220
Posts: 6587
Hofstadter's Law: It always takes longer than you expect, even when you take into account Hofstadter's Law.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
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);
}
Logged

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.

Offline Offline
Edison Member
*
Karma: 116
Posts: 2205
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

I would do this instead:

Code:
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().
Logged

Offline Offline
Jr. Member
**
Karma: 0
Posts: 77
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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
Logged

Pages: [1]   Go Up
Jump to: