If you live for wrangling I2C and reading data sheets, FRAM is easy to use.
If not, use @robtillaart's library and never look back:
a7
If you live for wrangling I2C and reading data sheets, FRAM is easy to use.
If not, use @robtillaart's library and never look back:
a7
What do you mean by
forming
Sorry if I am sounding thick, but I don't understand. Do you mean EEPROM sockets and the FRAM will fit in those sockets? Confused in Canada.
Yes there are the same pinout arrangement but the package is a bit bigger. You can save as much data as you want but you cannot run code from them with an Arduino as it is in the data space, not the code space. Adafruit has a module that has the FRAM already on it:
If you want the Arduino can hold several formulas for you and with either a keyboard, selector switch, push buttons, etc you could select the menu you want, With the FRAM you could easily keep time to the second that the program has run allowing seamless restarting. Add a RTC (Real Time Clock) and you can have it start before you get there.
You could also consider writing an interpreter for the Arduino with the instructions to be interpreted residing in the FRAM memory. The FRAM program would be specifically for your type of operation.
Given that the FRAM has an I2C interface, the interpreter would run so slowly that you'd want to stick a fork in your eye.
This is certainly true, but making bread dough is also as slow as molasses in January. Pretty well matched!
You could also have a big capacitor charged from your supply.
If supply stops, the capacitor will take over.
Your mcu should detect the power failure.
The cap should have sufficient capacity to save your current status to eeprom...
If power comes available again, eeprom can be loaded to set the ststus if the program where it was..
This means that you will need sufficient status variables to reconstruct the last status of your program...
This method will do less eeprom writing. Eeprom has limited writing cycles... if you updat status variables a million times per second you will wear out eeprom pretty fast...
I faced the power loss issue on my daily check-in device for seniors. I ended up keeping track of the state of the device. When the state changes, I save the new state in one of the four unused Alarm 1 registers of the DS3231 RTC, which is backed up by a coin cell, so never esperiences a power loss. On power up, I read in the last state, and take the appropriate action. And since the registers are ram, there's no risk of too many writes causing a problem.
But my needs were simpler than yours. It seems to me that in some cases what you do when power is restored depends on how long the power has been off. So you would have to think through the logic of what to do. But you can divide up the process into states, even one state per minute of the process if necessary, and somehow save the current state to non-volatile memory. One byte would let you distinguish between 256 states, more than one per minute of a 4-hour process. That might be enough. Then on power up, you would read in the last known state, and decide what to do.
Describe the states in the dough-preparing process, something like:
State 0: load ingredients into mixing bowl for 0 minutes
State 1: speed 3 mixing for 5 minutes
State 2: speed 2 kneading/mixing for 5 minutes
State 3: proofing temperature to 30c/85f
State 4: speed 0 resting for one hour
State 5: proofing temperature off/ambient at 21c/70f
State 6: speed 1 punch-down for 0.1 minute
State 7: speed 2 kneading for 5 minutes
State 8: speed 0 rest before baking
I can imagine a circular gear with pins or holes that rotates to indicate/initiate the next state.
[Edit] I see @ShermanP already said this... sry.
That means your code CANNOT assume any variable has a value set previously in your code! Can you program for that?
That's right. Any value that needs to be retained over a power outage has to be saved in non-volatile memory, then reloaded automatically during reboot. So in the OP's case, at the beginning of each one-minute state, he would save the state number and the current time of day. Then on any reboot, he would read back in the last state number and its beginning time, compare that time with the current time of day to determine how long the power was off, and then decide what to do.
The DS3231 has four register bytes containing the alarm1 time, and three bytes containg the alarm2 time. But if you aren't using the alarms, you can write whatever you want in those registers. I gave up trying to use DS3231 libraries for this kind of thing because they just aren't set up to do this kind of stuff.
Ok program is written. Very simple program.
I’ve decided to do no switching between types of bread and to just keep it simple. I could as someone mentioned use a battery pack (USB power bank) to keep the arduino alive easily enough. But it’d be interesting to play around with the EEPROM for the sake of learning.
Things I’ll likely add:
But for the most part this is a working mixer controller.
/*
Adapted from Blink.
*/
unsigned long seconds = 1000; // seconds defined to make the program human readable and is of course 1000 milliseconds
unsigned long minutes = 60000; // minutes defined to make the program human readable and is of course 60000 milliseconds
int x=0; // variable for for loop #1 (combine ingredients pulses)
int fold=7; // time in seconds mixer runs to "fold" dough
int mix=1; // time in minutes mixer runs to "mix" dough
int autolyse=20; // time in minutes to "autolyse" dough
int rest=30; // time in minutes to "rest" dough
void setup() // the setup function runs once when you press reset or power the board
{
pinMode(LED_BUILTIN, OUTPUT); // initialize digital pin LED_BUILTIN (pin D13) as an output for mixer
pinMode(12, OUTPUT); // initialize digital pin D12 as an output for buzzer
// 1. Combine MIXING on/off pulse for 1/2 minute (3 seconds of on/offs run 10 times)
for (int x = 0; x < 9; x++) // number of pulses (for loop)
{
digitalWrite(LED_BUILTIN, HIGH); // turn the LED on (HIGH is the voltage level)
delay(1*seconds); // wait for a set amount of on time
digitalWrite(LED_BUILTIN, LOW); // turn the LED off by making the voltage LOW
delay(2*seconds); // wait for a set amount of off time
}
// 2. Gluten Development MIX Part 1 (run for "mix" minutes)
digitalWrite(LED_BUILTIN, HIGH); // turn the LED on (HIGH is the voltage level)
delay(mix*minutes); // run for a set amount of on time
// 3. Autolyse for "autolyse" minutes
digitalWrite(LED_BUILTIN, LOW); // turn the LED off by making the voltage LOW
delay(autolyse*minutes); // wait for a set amount of off time
// 4. Gluten Development MIX Part 2a (mix for "mix" minutes) AND Add Salt (BUZZER)
digitalWrite(LED_BUILTIN, HIGH); // turn the LED on (HIGH is the voltage level)
digitalWrite(12, HIGH); // turn the BUZZER ON (Pin 12)
delay(mix*minutes); // wait for a set amount of on time
// Wait 1 minute
digitalWrite(LED_BUILTIN, LOW); // turn the LED off by making the voltage LOW
digitalWrite(12, LOW); // turn the BUZZER OFF (Pin 12)
delay(1*minutes); // wait for a set amount of off time
// Gluten Development MIX Part 2b (mix for "mix" minutes) AND Add Salt (if forgot) (BUZZ'R)
digitalWrite(LED_BUILTIN, HIGH); // turn the LED on (HIGH is the voltage level)
digitalWrite(12, HIGH); // turn the BUZZER ON (Pin 12)
delay(mix*minutes); // wait for a set amount of on time
// 5. Rest for "rest" minutes #1
digitalWrite(LED_BUILTIN, LOW); // turn the LED off by making the voltage LOW
digitalWrite(12, LOW); // turn the BUZZER OFF (Pin 12)
delay(rest*minutes); // wait for a set amount of off time
// 6. Fold #2 - Run Mixer for "fold" seconds
digitalWrite(LED_BUILTIN, HIGH); // turn the LED on (HIGH is the voltage level)
delay(fold*seconds); // wait for a set amount of on time
// 7. Rest for "rest" minutes #2
digitalWrite(LED_BUILTIN, LOW); // turn the LED off by making the voltage LOW
delay(rest*minutes); // wait for a set amount of off time
// 8. Fold #3 - Run Mixer for "fold" seconds
digitalWrite(LED_BUILTIN, HIGH); // turn the LED on (HIGH is the voltage level)
delay(fold*seconds); // wait for a set amount of on time
// 9. Rest for "rest" minutes #3
digitalWrite(LED_BUILTIN, LOW); // turn the LED off by making the voltage LOW
delay(rest*minutes); // wait for a set amount of off time
// 10. Remove Dough - Run Mixer for "fold" seconds to ball dough
digitalWrite(LED_BUILTIN, HIGH); // turn the LED on (HIGH is the voltage level)
delay(fold*seconds); // wait for a set amount of on time
digitalWrite(LED_BUILTIN, LOW); // turn the LED off by making the voltage LOW
delay(10); // wait for a set amount of off time
digitalWrite(12, HIGH); // turn the BUZZER ON (Pin 12) to alert completion
delay(1*minutes); // wait for a set amount of on time
digitalWrite(12, LOW); // turn the BUZZER OFF (Pin 12)
delay(5*minutes); // wait for a set amount of off time
digitalWrite(12, HIGH); // turn the BUZZER ON again (Pin 12) to alert completion
delay(1*minutes); // wait for a set amount of on time
digitalWrite(12, LOW); // turn the BUZZER OFF (Pin 12)
delay(10); // wait for a set amount of off time
}
void loop() {
// put your main code here, to run repeatedly:
}
And… I’ve already had a few glitches mid first real run (with dough).
Brownout reboot. You drew too much power from the power supply or through a microcontroller pin. Have you posted a wiring diagram (maybe I missed it).
I don’t know if it was a brown out on the arduino. I ran a test program (actually powering the mixer through 5 or 6 complete cycles (with shortened rest times for brevity) without a reset). I think I bumped something.
I have the Arduino feeding a 5 volt SSR directly. I’ve done this on several projects with the same SSR and it seems to work well.
The data sheet shows the insides, with protection diodes, but most of the "examples" also show a diode/transistor/MOSFET circuit to actuate the SSR.
p.s. I was tinkering with your code. I think you might like a Serial Monitor output as it runs...
1. PULSING 123456789. Complete.
2. KNEADING 1. Complete.
3. PROOFING 1. Complete.
4. KNEADING 2. Complete.
5. RESTING 1. Complete.
6. PROOFING 2. Complete.
7. RESTING 2. Complete.
8. FOLDING 2. (where is fold 1?). Complete.
9. RESTING 3. Complete.
10. FOLDING 3. Complete.
11. RESTING 4. Complete.
12. BALLING. Complete.
// https://forum.arduino.cc/t/select-between-groups-of-code-retain-position-in-code-loop-after-power-loss/1437036/33
unsigned long seconds = 1000;
unsigned long minutes = 60000;
int fold = 7; // time in seconds mixer runs to "fold" dough
int mix = 1; // time in minutes mixer runs to "mix" dough
int autolyse = 20; // time in minutes to "autolyse" dough
int rest = 30; // time in minutes to "rest" dough
int pulses = 9; // number of pulses in combine stage
int buzz = 12; // buzzer pin
void setup() // the setup function runs once when you press reset or power the board
{
Serial.begin(115200); // start serial communications with Serial Monitor
pinMode(LED_BUILTIN, OUTPUT); // initialize digital pin LED_BUILTIN (pin D13) as an output for mixer
pinMode(buzz, OUTPUT); // initialize digital pin D12 as an output for buzzer
// 1. Combine MIXING on/off pulse for 1/2 minute (3 seconds of on/offs run 10 times)
Serial.print(" 1. PULSING. ");
for (int x = 0; x < 9; x++) // number of pulses (for loop)
{
Serial.print(x + 1);
digitalWrite(LED_BUILTIN, HIGH); // turn the LED on (HIGH is the voltage level)
delay(1 * seconds); // wait for a set amount of on time
digitalWrite(LED_BUILTIN, LOW); // turn the LED off by making the voltage LOW
delay(2 * seconds); // wait for a set amount of off time
}
Serial.println(". Complete.");
// 2. Gluten Development MIX Part 1 (run for "mix" minutes)
Serial.print(" 2. KNEADING 1.");
digitalWrite(LED_BUILTIN, HIGH); // turn the LED on (HIGH is the voltage level)
delay(mix * minutes); // run for a set amount of on time
Serial.println(" Complete.");
// 3. Autolyse for "autolyse" minutes
Serial.print(" 3. PROOFING 1.");
digitalWrite(LED_BUILTIN, LOW); // turn the LED off by making the voltage LOW
delay(autolyse * minutes); // wait for a set amount of off time
Serial.println(" Complete.");
// 4. Gluten Development MIX Part 2a (mix for "mix" minutes) AND Add Salt (BUZZER)
Serial.print(" 4. KNEADING 2.");
digitalWrite(LED_BUILTIN, HIGH); // turn the LED on (HIGH is the voltage level)
digitalWrite(buzz, HIGH); // turn the BUZZER ON (Pin 12)
delay(mix * minutes); // wait for a set amount of on time
Serial.println(" Complete.");
// Wait 1 minute
Serial.print(" 5. RESTING 1.");
digitalWrite(LED_BUILTIN, LOW); // turn the LED off by making the voltage LOW
digitalWrite(buzz, LOW); // turn the BUZZER OFF (Pin 12)
delay(1 * minutes); // wait for a set amount of off time
Serial.println(" Complete.");
// Gluten Development MIX Part 2b (mix for "mix" minutes) AND Add Salt (if forgot) (BUZZ'R)
Serial.print(" 6. PROOFING 2.");
digitalWrite(LED_BUILTIN, HIGH); // turn the LED on (HIGH is the voltage level)
digitalWrite(buzz, HIGH); // turn the BUZZER ON (Pin 12)
delay(mix * minutes); // wait for a set amount of on time
Serial.println(" Complete.");
// 5. Rest for "rest" minutes #1
Serial.print(" 7. RESTING 2.");
digitalWrite(LED_BUILTIN, LOW); // turn the LED off by making the voltage LOW
digitalWrite(buzz, LOW); // turn the BUZZER OFF (Pin 12)
delay(rest * minutes); // wait for a set amount of off time
Serial.println(" Complete.");
// 6. Fold #2 - Run Mixer for "fold" seconds
Serial.print(" 8. FOLDING 2. (where is fold 1?).");
digitalWrite(LED_BUILTIN, HIGH); // turn the LED on (HIGH is the voltage level)
delay(fold * seconds); // wait for a set amount of on time
Serial.println(" Complete.");
// 7. Rest for "rest" minutes #2
Serial.print(" 9. RESTING 3.");
digitalWrite(LED_BUILTIN, LOW); // turn the LED off by making the voltage LOW
delay(rest * minutes); // wait for a set amount of off time
Serial.println(" Complete.");
// 8. Fold #3 - Run Mixer for "fold" seconds
Serial.print("10. FOLDING 3.");
digitalWrite(LED_BUILTIN, HIGH); // turn the LED on (HIGH is the voltage level)
delay(fold * seconds); // wait for a set amount of on time
Serial.println(" Complete.");
// 9. Rest for "rest" minutes #3
Serial.print("11. RESTING 4.");
digitalWrite(LED_BUILTIN, LOW); // turn the LED off by making the voltage LOW
delay(rest * minutes); // wait for a set amount of off time
Serial.println(" Complete.");
// 10. Remove Dough - Run Mixer for "fold" seconds to ball dough
Serial.print("12. BALLING. ");
digitalWrite(LED_BUILTIN, HIGH); // turn the LED on (HIGH is the voltage level)
delay(fold * seconds); // wait for a set amount of on time
digitalWrite(LED_BUILTIN, LOW); // turn the LED off by making the voltage LOW
delay(10); // wait for a set amount of off time
digitalWrite(buzz, HIGH); // turn the BUZZER ON (Pin 12) to alert completion
delay(1 * minutes); // wait for a set amount of on time
digitalWrite(buzz, LOW); // turn the BUZZER OFF (Pin 12)
delay(5 * minutes); // wait for a set amount of off time
digitalWrite(buzz, HIGH); // turn the BUZZER ON again (Pin 12) to alert completion
delay(1 * minutes); // wait for a set amount of on time
digitalWrite(buzz, LOW); // turn the BUZZER OFF (Pin 12)
delay(10); // wait for a set amount of off time
Serial.println(" Complete.");
}
void loop() {
// put your main code here, to run repeatedly:
}
Great idea! I guess that could be output to an LCD? I was thinking of a small strip of LEDs but serial is a much better looking and more customizable idea.