Writing Arduino Code

Joined
19 Jan 2006
Messages
558
Reaction score
32
Location
Wiltshire
Country
United Kingdom
I don't suppose anyone on here is handy with Arduino code writing?
I'm completely new to code writing & struggling to translate everything I've read/watched into something that makes sense!
I've used somebody else's code as a template & made some adjustments to certain parameters. This works to a degree, but uses the standard delay commands, which cause the known issues. I'd like to use millis instead, but I'm struggling with rewriting the code to suit.

If any kind soul is able to help, I'll explain exactly what I'm trying to achieve.

TIA.
 
I wish to trigger a fume extraction unit when I pick up my soldering iron. The iron is a JBC that is set to hibernate (no heat) when in the holder. I have the Arduino connected to a current sensor to monitor the extra current drawn when the iron is heating.
I took the Arduino code from a guy who used the same principle to activate a shop vac when he uses his table saw. As i said previously, I've tweaked the code to suit my setup & it fundamentally works.
However, it uses the delay command, which makes the Arduino dumb to further triggers during that delay period. So if you momentarily put the iron back in the holder & pick it up again during that time, the device ignores that & continues with the delay resulting in a power down of the extraction before being triggered again.
So what I'm wanting, is a retrigger to extend that delay for the predetermined period.
Would it help if I posted the original code?

Many thanks for the reply BTW!
 
#define CURRENT_SENSOR_PIN A0 // Current sensor is connected to analog pin A0
#define RELAY_PIN 2 // Relay module is connected to digital pin 2
#define RELAY_LOGIC LOW //Set to LOW if your relay is activated by a ground signal. Set to HIGH if your relay is activated by a 5V signal. If your relay is active at bootup, and turns off when CURRENT_THRESHOLD is met, then try changing this setting to the opposite.
#define CURRENT_THRESHOLD 520 // The analog value above which the relay shall be triggered
#define CURRENT_SAMPLE_PERIOD 500 // The number of milliseconds to sample the current reading
#define RELAY_STARTUP_DELAY 2000 // The number of milliseconds to delay before activating relay after tool has started
#define RELAY_SHUTOFF_DELAY 5000 // The number of milliseconds to delay shutting off the relay after the tool has been shutoff

int analogValue = 0; // Stores ADC values read in from the current sensor
unsigned long stopwatch = 0; // Used to keep track of elapsed time
boolean relayPinState = HIGH; // Stores the current state of the relay pin

void setup() {
Serial.begin(9600);
pinMode(RELAY_PIN,OUTPUT);
}

void loop() {
analogValue = 0; // Initialize analogValue to a known state
stopwatch = millis(); // Store a snapshot of the current time since the program started executing

// Collect the max ADC value from the current sensor for the predetermined sample period
while(millis() - stopwatch < CURRENT_SAMPLE_PERIOD) {
analogValue = max(analogValue,analogRead(CURRENT_SENSOR_PIN));
Serial.println(analogValue);
}

// If the max ADC value from the current sensor exceeds the threshold, activate the relay
if(analogValue > CURRENT_THRESHOLD) {
delay(RELAY_STARTUP_DELAY);
relayPinState = RELAY_LOGIC;
}
// Otherwise if the relay was just activated, wait for the predetermined shutoff delay and set the state to HIGH
else {
if(relayPinState == RELAY_LOGIC) {
delay(RELAY_SHUTOFF_DELAY);
relayPinState = !relayPinState;
}
}
digitalWrite(RELAY_PIN,relayPinState); // Write the RELAY_PIN to the correct state
}
 
I'm sorry, I said I was rusty!
I'm pretty sure you need to setup another timer interval using millis (), something like:

if(analogValue > CURRENT_THRESHOLD) {
time=millis();
while(millis() < time + RELAY_STARTUP_DELAY);
relayPinState = RELAY_LOGIC;

I'm equally sure that the above code will not just work! ;)

I need to get back to my PC, where I have played with millis () before!

If I can get it to compile, I'm uploading it & testing it in a real world environment.
It's well worth downloading an emulator - it will allow you to play with code and test it on the fly, very quickly showing you what does and doesn't work.
Far better than compiling code, downloading it and then experimenting on the real thing!
 
Last edited:
I'm sorry, I said I was rusty!
I'm pretty sure you need to setup another timer interval using millis (), something like:

if(analogValue > CURRENT_THRESHOLD) {
time=millis();
relayPinState = RELAY_LOGIC;
while(millis() < time + RELAY_STARTUP_DELAY);

I'm equally sure that the above code will not just work! ;)

I need to get back to my PC, where I have played with millis () before!


It's well worth downloading an emulator - it will allow you to play with code and test it on the fly, very quickly showing you what does and doesn't work.
Far better than compiling code, downloading it and then experimenting on the real thing!
No need to apologise - I need all the help I can get!
I'll hopefully get back onto this tomorrow evening.
Many, many thanks for your help so far.
 
I like you found the shop vac code terrible.
All the versions I saw were bouncing the relay, did not keep the vac running (as you found) if tool restarted in timeout period. And had no safety features. Hence I wrote my one terrible code that does work (although I never fixed the fact that it crashes if left on for two weeks when the timer returns to zero).

So, first - you can have a copy of my code and give it a go. But will not be for a week as soon not have that computer on me.

Second, I am writing this on a phone so cannot write the code. So my suggestions are made without and code - sorry.

To address your issue I relpaxed the tow delay lines with a 'flag' variable. Wherein the flag is made to be the time + runon time everytime the current goes high (the first delay line in your code) and remived second delay line in your code.

Then a if comand on your final line that controls the relay. Wherein the relay is switched on if the time less than time+runon time and switched off if the actual time is greater than the. Time + running time.

Hope this helps a bit
Sfk
 
Note that there was another error that I found in everyone's vac code that caused issues from r me.
Because you are looking fot the current sensor to go high about 100 times a second, and if it does go high you switch on the vac, then any single spurious current high will trigger the vac. So I got un-called for vac startups fairly frequency as I had my threshold quite low and a low quality current sensor.

Might not be an issue for you, so don't do this yet.
But fyi I put a counter loop on my current sensor such that when it saw a trigger it would check it again for the the next 25 (sorry cannot remember how many) times and only if they were all high does it trigger the vac.
It was a if statement and if high would activate a loop to check current sensor 25 times and if all high would flag to start the vac, but if any of the checks are a low it would drop out of the loop and not activate the fan.

Sfk
 
Last edited:
Many thanks for everyone's help so far.
There are numerous non-block delay libraries available - I'd be looking to use one of those. This article has some good explanations of different ways of achieving what you need, and suggests a library to use.

Coding Timers and Delays in Arduino : 8 Steps - Instructables
Thanks for the link, I think I've stumbled across that page already - embarrassingly, it didn't offer me any eureka moments. I will study it again & see if any pennies drop.

So, first - you can have a copy of my code and give it a go. But will not be for a week as soon not have that computer on me.
That would be fantastic if you get a chance! Many thanks.
Note that there was another error that I found in everyone's vac code that caused issues from r me.
Because you are looking fot the current sensor to go high about 100 times a second, and if it does go high you switch on the vac, then any single spurious current high will trigger the vac. So I got un-called for vac startups fairly frequency as I had my threshold quite low and a low quality current sensor.

Might not be an issue for you, so don't do this yet.
But fyi I put a counter loop on my current sensor such that when it saw a trigger it would check it again for the the next 25 (sorry cannot remember how many) times and only if they were all high does it trigger the vac.
It was a if statement and if high would activate a loop to check current sensor 25 times and if all high would flag to start the vac, but if any of the checks are a low it would drop out of the loop and not activate the fan.

Sfk
My soldering iron uses PWM, so draws (apparently) random spikes of full current while in use. I extended the sample period to 4 seconds to prevent erroneous power downs of the extraction while the iron is in use. A bit crude & means the extraction switches on up to 4 secs after lifting the iron, but otherwise it cured the issue. Not a problem as the iron takes a few secs to reach operating temp anyway.

I will keep playing around with it.
Thanks again.
 
I think I may have cracked it!
Once I'd worked out I needed to instal millisDelay into the library, the changes were actually quite simple.
I've also reduced the current sample period by a second - all good. The millis overflow issue shouldn't affect it either, as the workbench is switched off every night.
It seems to be working as I'd hoped, but I'll give it a longer term real world test tomorrow.
Thanks again to all for pointing me in the right direction.
Here is the code:

#define CURRENT_SENSOR_PIN A0 // Current sensor is connected to analog pin A0
#define RELAY_PIN 2 // Relay module is connected to digital pin 2
#define RELAY_LOGIC LOW //Set to LOW if your relay is activated by a ground signal. Set to HIGH if your relay is activated by a 5V signal. If your relay is active at bootup, and turns off when CURRENT_THRESHOLD is met, then try changing this setting to the opposite.
#define CURRENT_THRESHOLD 800 // The analog value above which the relay shall be triggered
#define CURRENT_SAMPLE_PERIOD 3000 // The number of milliseconds to sample the current reading
#include <millisDelay.h>

int analogValue = 0; // Stores ADC values read in from the current sensor
unsigned long stopwatch = 0; // Used to keep track of elapsed time
boolean relayPinState = HIGH; // Stores the current state of the relay pin
millisDelay relayDelay;


void setup() {
Serial.begin(9600);
pinMode(RELAY_PIN,OUTPUT);
}

void loop() {
analogValue = 0; // Initialize analogValue to a known state
stopwatch = millis(); // Store a snapshot of the current time since the program started executing

// Collect the max ADC value from the current sensor for the predetermined sample period
while(millis() - stopwatch < CURRENT_SAMPLE_PERIOD) {
analogValue = max(analogValue,analogRead(CURRENT_SENSOR_PIN));
Serial.println(analogValue);
}

// If the max ADC value from the current sensor exceeds the threshold, activate the relay
if(analogValue > CURRENT_THRESHOLD) {
relayPinState = RELAY_LOGIC;
relayDelay.start(25000);
}
// Otherwise if the relay was just activated, wait for the predetermined shutoff delay and set the state to HIGH
else {
if (relayDelay.justFinished()) {
relayPinState = !relayPinState;
}
}
digitalWrite(RELAY_PIN,relayPinState); // Write the RELAY_PIN to the correct state
}
 
Reading your code made me realise just how rusty I have become, though I think I can offer a refinement:-

When trying to detect if an event occurred rather than a noisy signal, I have used the 'streak detection' method.
1. Make a function which is called on every iteration of the loop().
2. In this function include the following logic (apologies for the pseudo-code, it's a rust thing).
If (current > threshold value)
{
count++ ; count up if you detect the iron is on
}
else count--; if no current seen then decrement the counter

If (count > 25) whatever value defines the point where the ventilation is triggered, or indeed the fan's ON delay.

//NOTE: there is a command called CONSTRAIN which will stop/limit/cap the value of 'count'. You can use this to adjust the stopping delay too.
{
TurnFanOn;
}

If (count < 5)
{
TurnFanOff;

Yes, I too am truly rusty...
MM
}
 
Back
Top