Help to modify Arduino code

Arduino projects on the go
Scott Todd
Posts: 66
Joined: 26 Mar 2018, 23:21

Help to modify Arduino code

Post by Scott Todd »

I want to add a timer to Phil's code and need some help. I have added a second momentary button to a transmitter. When pressed, I want it to start a two minute timer to simulate a tank of fuel. At the end, I would like it to momentarily hit the throttle kill switch. Then you can just reduce the throttle to turn the 'chirper' off and then throttle up if you like, or land.

It seem pretty straight forward. but I'm, struggling a bit. I keep trying to use the milli command to save the time when the button is pressed and then poll for it as the loop comes around.

My programming is really lacking. Any code junkis out there willing to help?
Martin
Posts: 745
Joined: 16 Feb 2018, 14:11
Location: Warwickshire

Re: Help to modify Arduino code

Post by Martin »

The millis() function returns an unsigned 32-bit value, so you need a variable of that type to hold the 'start time'.

uint32_t buttonPressedMillis;

You want that value to be remembered so you have to declare it outside of the loop() function. If you declare it inside loop() (unless you declare it static) then it could be forgotten between one call of loop() and the next.

So you need something like:

uint32_t buttonPressedMillis;
loop() {
...
if (buttonPressed) {
buttonPressedMillis = millis();
}
...
}

Then you need a way of calculating the time elapsed since the button was pressed. You can do this by just subtracting the start time from the current value of millis(). You might ask what happens when the millis() timer wraps round from its maximum value back to zero - but you don't need to worry because:

a) when you subtract one 32-bit unsigned from another, the result automatically takes care of wrapping problems.
b) it won't happen anyway unless you leave your Arduino powered up continuously for nearly fifty days.

So you'll have something like:

if (millis() - buttonPressedMillis >= 120000UL) {
... two minutes has elapsed so do something ...
}

two minutes in milliseconds is 120000 and the UL is a clue to the compiler that the quantity is an unsigned long (32-bits)

Don't forget that the test above will remain true for all subsequent calls of loop() unless buttonPressedMillis is changed. If you want to only do something (such as chirp the buzzer) for, say, two seconds, then you need to check for a range of times like this:

uint32_t millisSinceButtonPress = millis() - buttonPressedMillis;
if (millisSinceButtonPress >= 120000UL && millisSinceButtonPress < 122000UL) {
...chirp
}

The && (double ampersand) is part of the C++ language that checks if both sides of the && are true: normally it's just pronounced 'and' when you're reading the code. There is a similar thing consisting of two 'pipe' characters || (normally down near the z key on your keyboard) that does an 'or' test.

If you want to trigger something at a certain time, and then have some other action (such as a throttle position change) complete the process, then you might want to have some kind of 'mode' or 'stage' variable to remember what stage has been reached - this would also be declared outside loop(). Then you could set, say, stage = 0; when the program starts, stage = 1; when the timer starts, stage = 2; when it finishes, stage = 3 when the throttle is reduced and so on.
Ralkbirdy
Posts: 44
Joined: 25 Feb 2018, 13:10

Re: Help to modify Arduino code

Post by Ralkbirdy »

This is why Martin programs, and I build with balsa/Depron.
FBMinis
Posts: 55
Joined: 25 Feb 2018, 17:59

Re: Help to modify Arduino code

Post by FBMinis »

My guess is that Martin teaches programming because that was clear as water
User avatar
Phil_G
Posts: 602
Joined: 15 Feb 2018, 23:32
Contact:

Re: Help to modify Arduino code

Post by Phil_G »

I'd just buy a kitchen timer from Poundland :D
You need to do it Martins way Scott as the code as it stands is polled/timed rather than interrupt driven (it was my first ever Arduino project, so its embarrassingly basic, I never expected others might be interested). The timing is critical, you cant wait for anything, or do anything that distracts the processor for any length of time. Remember if its controlling an airborne missile you have to be 100% certain your modifications are bug free and there are no traps it can fall into, or there will almost certainly be a crash & the possibility of injury. You'd need throttle modes, if you just change the throttle channel the code will simply set it back again on the next loop. To be honest its really not worth it, Mike has a far, far superior Arduino encoder which does everything you could possibly want in a computer radio, including count-up and count-down timers.
Again, if it was me, I'd just go to Poundland for a timer :D
Cheers
Phil

PS I had a thought as I've been putting the dogs to bed.
You could replicate the inactivity timer code, its based on frame count so it wouldnt be as accurate as a millis() based timer, but then a Cox Babe Bee doesnt run out of juice accurately either :D
So you'd push a button to trigger it, 2 minutes later it times out and engages the throttle lock
(the software throttle lock, not the throttle lock switch, obviously)
If the throttle was open on timeout, the pips would happen automagically without any extra code (just like when you switch on with the throttle open)

Re code safety, I spend many hours testing every feasible condition in every possible combination before releasing anything, its not something I'd dismiss lightly :D

When I get a mo I'll port the interrupt driven ppm section from the Reeduino to the 7ch as there still seems
to be a niche for this 'simple' propo encoder and its not had an update in 4 years (yes, its 4 years. Scary eh?)
Cheers
Phil
Scott Todd
Posts: 66
Joined: 26 Mar 2018, 23:21

Re: Help to modify Arduino code

Post by Scott Todd »

Your code is great Phil! Its simple and fairly easy to follow. The PPM stream generator is a bit too efficient as its hard for newbs to follow but I understand a desire to make small code from a programmers perspective.

A bit more back story...I have converted a bunch of old metal box radios and given some to friends. I'm starting a trend at my local site (Thanks Phil ;)

Now that a few are getting the hang of S/C, we have talked about a bit more. The timer idea is to simulate a motor run such as an old cox .049

A press of the button starts the internal timer. At the end, it shuts the motor off. Now, just like yesteryear, you have to land. But for safety reasons (we fly in a city park surrounded) you may need the motor to get it back. Buy putting the Arduino in the same state as if the throttle cut has been toggled, you just have to cycle the throttle to bring it back alive.

We are thinking getting as many up as we can and everyone pushing their button at the same time. See who can land closes to home :) Mental timing and setting up for the approach...

And it gives me an objective to practice programming :) Of course I'l share if I get it working. If someone beats me too it, I'm not proud and will gladly use the code. There are plenty of other things I can do.

Thank you Martin and Phil ! ! !
belli
Posts: 39
Joined: 19 Feb 2018, 19:19

Re: Help to modify Arduino code

Post by belli »

I didn't know that Mikes' code was available...
Martin
Posts: 745
Joined: 16 Feb 2018, 14:11
Location: Warwickshire

Re: Help to modify Arduino code

Post by Martin »

Yes, good point about the safety aspect of modifying code that's driving out a critical signal in real time from the main loop. Probably best not to meddle with the code. Like Phil said, much safer to use a stand alone timer.

I write my transmitter programs so that the output signal to the RF module is interrupt driven - that way, providing that the main loop doesn't do anything disastrous like disable interrupts, the signal keeps getting sent regardless of what the main loop is doing. But that's no help to you as I've not done a proportional set, and hacking my reeds or single channel code to make it work in a proportional set would be a fairly major project.
Scott Todd
Posts: 66
Joined: 26 Mar 2018, 23:21

Re: Help to modify Arduino code

Post by Scott Todd »

I wasn't referring to safety as far as the code goes. That's pretty easy to vet on the bench. I meant someone finding themselves on the downwind side of the park and not making it back dead stick. The park is surrounded by streets, apartments, and houses. We also fly on one half where the other half is often hosting soccer games and such. A plane landing dead stick in the middle of a soccer game is not good.
Scott Todd
Posts: 66
Joined: 26 Mar 2018, 23:21

Re: Help to modify Arduino code

Post by Scott Todd »

So I've made some progress. I've added 6 lines of code but can't get it to work entirely. Instead of posting the entire thing, here are the lines as they would go in Phil's posted code. I'm using 2 seconds (approximately) for debugging. This seems like it roughly follows Phil's latest suggestion. I haven't wrote any code in 25 years so I'm a bit rusty.

40 static int timer = 2;
41 uint32_t buttonPressedMillis;
57 pinMode(timer, INPUT_PULLUP);
110 if (digitalRead(timer) == 0) tlock=1;
111 // if (digitalRead(timer) == 0) buttonPressedMillis = millis();
112 // if (millis() - buttonPressedMillis >= 2000UL) tlock=1;

This runs. When I press the button to ground pin 2, it activates the throttle cut function as Phil designed it. Cycling the throttle stick resets it. However, when I comment line 110 and un-comment the next two, it doesn't work.

I have tried lots of variations and don't get anything.

I wrote this simple sketch to light the LED for 2 seconds after a button press to test the millis() command and it works fine. But somehow, I can't connect the dots :(

/* Sketch to learn millis() Scott Todd 6/21/18
* press button to start timer and turn LED on
* After time, light goes off and waits for button
*/
uint32_t buttonPressedMillis;

static int ledPin = 13;
static int timer = 2;

void setup()
{
pinMode(ledPin, OUTPUT);
pinMode(timer, INPUT_PULLUP);
}

void loop()
{
if (digitalRead(timer) == 0)
{ buttonPressedMillis = millis();
digitalWrite(ledPin, HIGH);
}
if (millis() - buttonPressedMillis >= 2000UL)
{ digitalWrite(ledPin, 0);
}
}
Post Reply