Hi
for a change , I actually have most of my code done but there is just one small piece I need advice on
Let me explain what I am doing/trying to do
I have a 5" gauge ride on train . I want to keep a record of how far it has travelled. I could count the the laps ( which are 1/4 mile each) and write it in a book , but I know as sure as eggs is eggs I will sometimes forget to write it down before I switch off the power ( its an age thing).
I decided I need to get it to automatically save the data when it detects the power is falling.
I was pleased because I managed to work out how to make that happen by myself .
I have a super Capacitor that is charged by the power supply all the time its on. An interrupt detects when the PSU goes and the super cap gives me enough power to complete the save to eeprom
when I restart the arduino the first thing it does is reload the last saved data so I carry on where I left off .All that works great .
I also have an interrupt that counts wheel revolutions with a hall sensor.
I know that there are 5418.667 revolutions per mile. The arduino does the calculation and tells me
the result of total miles travelled and trip miles travelled this session . It calculates the trip from the total distance so far minus the last saved total distance. Its all displayed on an I2C LCD
All that works as well so my code which I will attach is fine and you dont need to change any of that
What I need is help as to why I cant add the one last little bit of code that I require
In the ISR that saves the data to memory, after saving I want it to clear the LCD and then write "SAVED" just so I know it succeeded
In the ISR I had tried
void MEMORY() {
EEPROM.writeDouble(0,y); // power failed save y value
lcd.clear ;
lcd.setCursor(0,0);
lcd.print("SAVED");
}
No matter what I write it saves the data ok but refuses to clear the screen and write " SAVED "
I dont know if its because I am using an I2C LCD rather than a normal one or if you cant put print statements in an ISR but it just seems to ignore the extra code. It compiles fine and loads it to the arduino. It just doesnt seem to take any notice of it.
Should I put it somewhere other than in the memory save ISR and if so where and how ?
Should I put it somewhere other than in the memory save ISR and if so where and how ?
Have the ISR change the value of a global boolean variable (declared as volatile) to true when the value is saved then in loop() when the value of the variable is true print your message and set the variable to false.
How often is the ISR triggered and how many writes to an EEPROM location can you safely do ?
The solution ov UKHeliBob is correct and you should implement that. I just wanted to tell you why your solution did not work. As you told you have an LCD that is connected by I2C. The I2C interface of the Arduino is interrupt driven, that means if you write some stuff to the interface it's copied to an internal buffer which then is processed one byte after the other by an ISR that is called by the I2C hardware once the next bus state is reached. The Wire library, which does the I2C stuff in the Arduino world, does all that stuff using busy wait loops, so it writes some bytes to a buffer and then waits for that buffer to be emptied by the interrupt. The problem occurs now because inside an ISR all other interrupts are blocked. So when you call your lcd.print() (or any other method on that object) the buffer is filled with the first few bytes to be transfered. Then the Arduino waits for the I2C interrupt to empty that buffer. As interrupts are blocked the buffer is never emptied and the Arduino waits forever, or in your case until the super cap is empty and power fails.
gfvalvo:
Pretty impressive that you know something like that to 7 significant figures ;D
I wouldnt say it was impressive , its easy really
Divide a mile ( 1609344 mm ) by the circumference of the wheel ( 297mm ) tells me how many revolutions it makes (5418.66666r )
I’m not saying that the fact you can do division is impressive. I’m saying that knowing the actual circumference of the wheel with an accuracy of one part in 10 MILLION is impressive. That’s what 7 significant figures means.
UKHeliBob:
Have the ISR change the value of a global boolean variable (declared as volatile) to true when the value is saved then in loop() when the value of the variable is true print your message and set the variable to false.
How often is the ISR triggered and how many writes to an EEPROM location can you safely do ?
Thanks for the fast answer , I shall give it a go .
As for number of ISR calls
I would expect it to power down after the end of my day driving or maybe when I stop for lunch and I guess
I will be playing a couple of days a week so about 4 calls a week. The eeprom is said to be good for about
100000 writes so I imagine the train , and I will both be worn out before the eeprom dies
It would have been so much easier to just save the data once a second without bothering about interrupts but that would have worn out the eeprom far too quickly hence the way I decided to go
DonRecardo:
I wouldnt say it was impressive , its easy really
Divide a mile ( 1609344 mm ) by the circumference of the wheel ( 297mm ) tells me how many revolutions it makes (5418.66666r )
gfvalvo:
I’m not saying that the fact you can do division is impressive. I’m saying that knowing the actual circumference of the wheel with an accuracy of one part in 10 MILLION is impressive. That’s what 7 significant figures means.
I am sorry I am not deliberately trying to appear thick but how do you get to believe I measured the wheel to one part in 10 million
I wrapped a piece of paper around the wheel and measured it with a ruler
I could instead have measured the wheels diameter with a digital caliper and said its near enough 94.5 mm diameter and used pi instead to get the same result
even if I was 0.5mm out on the diameter it would still only be out by about 10 meters on a mile
pylon:
The solution ov UKHeliBob is correct and you should implement that. I just wanted to tell you why your solution did not work. As you told you have an LCD that is connected by I2C. The I2C interface of the Arduino is interrupt driven, that means if you write some stuff to the interface it's copied to an internal buffer which then is processed one byte after the other by an ISR that is called by the I2C hardware once the next bus state is reached. The Wire library, which does the I2C stuff in the Arduino world, does all that stuff using busy wait loops, so it writes some bytes to a buffer and then waits for that buffer to be emptied by the interrupt. The problem occurs now because inside an ISR all other interrupts are blocked. So when you call your lcd.print() (or any other method on that object) the buffer is filled with the first few bytes to be transfered. Then the Arduino waits for the I2C interrupt to empty that buffer. As interrupts are blocked the buffer is never emptied and the Arduino waits forever, or in your case until the super cap is empty and power fails.
Thanks for explaining , what you said makes sense . I havent done much with interrupts so dont know all the ins and outs of but thats a bit more that I have learned ,
thank you
DonRecardo:
I am sorry I am not deliberately trying to appear thick but how do you get to believe I measured the wheel to one part in 10 million
It might be considered an academic point, but it’s actually important when considering the accuracy of measurements. You stated that the revolutions per mile is 5418.667. That’s 7 significant figures or 1 part in 10 Million. In order to truly be that accurate the measurements you used in the calculation need to be at least that accurate.
No problem with mm per mile, that’s an exact number: 1609344. But, you stated that the wheel circumference is 297 mm. That’s an accuracy of 3 significant figures or 1 part in 1000. So, any calculation that you do with that number can be no more accurate than 1 part in 1000. Thus, you can only state the revolutions per mile to that accuracy: 5420.
Basically, you’re confusing precision with accuracy.
gfvalvo:
It might be considered an academic point, but it’s actually important when considering the accuracy of measurements. You stated that the revolutions per mile is 5418.667. That’s 7 significant figures or 1 part in 10 Million. In order to truly be that accurate the measurements you used in the calculation need to be at least that accurate.
No problem with mm per mile, that’s an exact number: 1609344. But, you stated that the wheel circumference is 297 mm. That’s an accuracy of 3 significant figures or 1 part in 1000. So, any calculation that you do with that number can be no more accurate than 1 part in 1000. Thus, you can only state the revolutions per mile to that accuracy: 5420.
Basically, you’re confusing precision with accuracy.
Well thanks for explaining. I couldnt see where your were comming from at first . I will accept what you say about not really being able to quote accurately better than 5420 but as thats within 1.5 wheel turns of 5418.6667 which I had quoted or about 17.5 inches out on a mile I think I will live with that, after all I probably gain more than 17.5 inches due to wheel spin
The main thing is , It now all works and I get a message telling me its saved
UKHeliBob:
Are you sure that the ISR will be triggered when the power fails ?
What will cause pin 2 to go LOW when the power fails ?
Yes I tried it several times and it works a treat
I run 2 voltages on my train
24V ( it comes nearer 26 when full charged) This runs everything except the arduino
5V regulated down from the 24V line for the arduino and LCD
I have a voltage divider on the 24 volt line that gives me 4v to 5v depending on the battery charge level
I take this 4v to 5v to pin 2 and it drops as soon as I kill the main batteries
the regulated 5v to the arduino goes through a diode and sits charging a supercap which powers the arduino .and LCD
the diode stops the cap discharging back through the rest of the circuits
When the main power drops the 24v line drops instantly and so triggers the interrupt on pin 2
but the super cap powers the arduino and LCD for several minutes before discharging too much
Once it tells me it has saved the data , ( which it now does thanks to your help) I then switch off the connection from the super cap to the arduino
I will try to put a bit of a diagram on this post .
on the diagram JP2 goes to pin 2 on the arduino
JP3 is the uninterruptable power supply from the super cap which goes to power the arduino
JP1 top to bottom is
24V
5V
GND
Hmmmm there seems to be no add file button on this quick reply window . I will have to send it as
a seperate post