Hi everyone! My first post. If it is in the wrong spot, I'm sorry. I have an Area51 project for our train club where I launch a balloon with a controlled fan (like the old Johnny Astro) and bring it back down. It is my first code and it is probably not a great attempt, but it works. First I had the code on just a loop to test, then I put it on a button. The unit is running on a 10,000mA phone charging battery, which I found out will turn off in one minute if not used. So currently, I have a 15 second delay to keep the button from being pushed right away, but now I need an additional timer for say, 15 seconds, to repeat the program so that the battery remains active.
I am posting the code and hope that you will critique it. I hope that someone can also help me with a simple solution to the above problem. Thanks for your help.
/*
Turns on and off and controls a motor attached to digital pin 9,
when pressing a pushbutton attached to pin 2.
The circuit:
- DC Motor attached from pin 9 to ground through an N-Channel Mosfet
- pushbutton attached to pin 2 from +5V
- 10K resistor attached to pin 2 from ground
created 2024
by Don Whatley
modified 30 Aug 2024
by KEith Ratliff
There is example code is in the public domain for fading LED and a momentary Switch.
https://www.arduino.cc/en/Tutorial/BuiltInExamples/Button
*/
// constants won't change. They're used here to set pin numbers:
const int buttonPin = 2; // the pin that the pushbutton is attached to
const int MOTORPin = 9; // MOTOR connected to digital pin 9
// variables will change:
int buttonState = 0; // current state of the button
int lastButtonState = 0; // previous state of the button
void setup() {
// initialize the button pin as a input:
pinMode(buttonPin, INPUT);
}
void loop() {
// read the pushbutton input pin:
buttonState = digitalRead(buttonPin);
// compare the buttonState to its previous state
if (buttonState != lastButtonState) {
// if the state has changed, increment the counter
if (buttonState == HIGH) {
// if the current state is HIGH then the button went from off to on:
// Delay a little bit to avoid bouncing
delay(50);
}
// fade in from min to max in increments of 3 points:
for (int fadeValue = 0 ; fadeValue <= 200; fadeValue += 3) {
// sets the value (range from 0 to 200):
analogWrite(MOTORPin, fadeValue);
// wait for 60 milliseconds to see the dimming effect
delay(60);
}
delay(10000); // wait 10 seconds
// fade out from max to min in increments of 3 points:
for (int fadeValue = 200 ; fadeValue >= 0; fadeValue -= 3) {
// sets the value (range from 0 to 200):
analogWrite(MOTORPin, fadeValue);
// wait for 60 milliseconds to see the dimming effect
delay(60);
}
delay(15000); // wait 15 seconds
}
}
With manual switches, look at when they change state, not their level.
Always show us a good schematic of your proposed circuit.
Show us good images of your ‘actual’ wiring.
Give links to components.
For readability, place { and } on separate lines by themselves, place each line of code on a separate line.
In the Arduino IDE, use CtrlT or CMDT to format your code, then copy the complete sketch.
Try this sketch version:
//
//================================================^================================================
//
// https://forum.arduino.cc/t/timer-or-push-button-to-trigger-motor/1298664/2
//
//
//
// Version YY/MM/DD Comments
// ======= ======== ========================================================================
// 1.00 24/09/04 Running code, we still need to add button switch action
//
//
//
// Notes:
//
#define PRESSED HIGH //+5V---[Switch]---Pin---[10k]---GND
#define RELEASED LOW
#define ENABLED true
#define DISABLED false
#define MOTORon HIGH
#define MOTORoff LOW
// G P I O s
//================================================^================================================
//
const byte buttonPin = 2;
const byte MOTORPin = 9;
const byte heartbeatLED = 13;
// V A R I A B L E S
//================================================^================================================
//
bool balloonFlag = DISABLED;
int fadeCounter;
int buttonState;
int lastButtonState = RELEASED;
//timing stuff
unsigned long heartbeatTime;
unsigned long switchesTime;
unsigned long automaticTime;
unsigned long commonTime;
unsigned long machineTime;
unsigned long automaticInterval = 30ul * 1000; //30 seconds, should be less than the auto shut off time
// S t a t e M a c h i n e
//================================================^================================================
//the states in our machine
enum STATES : byte
{
STARTUP, BALLOONup, WAITINGup, BALLOONdown, WAITINGdown
};
STATES mState = STARTUP;
// s e t u p ( )
//================================================^================================================
void setup()
{
Serial.begin(115200);
pinMode(heartbeatLED, OUTPUT);
pinMode(MOTORPin, OUTPUT);
pinMode(buttonPin, INPUT);
Serial.println("System Restart");
} //END of setup()
// l o o p ( )
//================================================^================================================
void loop()
{
//======================================================================== T I M E R heartbeatLED
//is it time to toggle the heartbeat LED ?
if (millis() - heartbeatTime >= 500ul)
{
//restart this TIMER
heartbeatTime = millis();
//toggle the heartbeat LED
digitalWrite(heartbeatLED, digitalRead(heartbeatLED) == HIGH ? LOW : HIGH);
}
//======================================================================== T I M E R switches
//is it time to scan our switches ?
if (millis() - switchesTime >= 50ul)
{
//restart this TIMER
switchesTime = millis();
checkSwitches();
}
//======================================================================== T I M E R automatic
//if the balloon is not moving, is it time to automatically move the balloon ?
if (mState == STARTUP && millis() - automaticTime >= automaticInterval)
{
Serial.println("Balloon automatic operation started");
//starting the balloon sequence automatically
mState = BALLOONup;
//motor speed starts out at 0
fadeCounter = 0;
//restart the TIMER
commonTime = millis();
}
//======================================================================== T I M E R machine
//is it time to check our State Machine ?
if (millis() - machineTime >= 10ul)
{
//restart this TIMER
machineTime = millis();
checkMachine();
}
//================================================
//other non blocking code goes here
//================================================
} //END of loop()
// c h e c k M a c h i n e ( )
//================================================^================================================
void checkMachine()
{
//================================================
//service the current "machine state"
switch (mState)
{
//========================
case STARTUP:
{
//do startup stuff
}
break;
//======================== increase the speed from 0 to 200
case BALLOONup:
{
//has the common TIMER expired ?
if (millis() - commonTime >= 60ul)
{
//restart TIMER
commonTime = millis();
//increase motor speed
analogWrite(MOTORPin, fadeCounter);
fadeCounter = fadeCounter + 3;
//have we reached maximum speed ?
if (fadeCounter > 200)
{
Serial.println("Balloon is at maximum");
//next State
mState = WAITINGup;
//restart the TIMER
commonTime = millis();
break;
}
}
}
break;
//======================== wait here for 10 seconds
case WAITINGup:
{
//has the common TIMER expired ?
if (millis() - commonTime >= 10000ul)
{
Serial.println("Balloon is going down");
fadeCounter = 200;
//next State
mState = BALLOONdown;
//restart TIMER
commonTime = millis();
break;
}
}
break;
//======================== decrease the speed from 200 to 0
case BALLOONdown:
{
//has the common TIMER expired ?
if (millis() - commonTime >= 60ul)
{
//restart TIMER
commonTime = millis();
//decrease motor speed
analogWrite(MOTORPin, fadeCounter);
fadeCounter = fadeCounter - 3;
//have we reached minimum speed ?
if (fadeCounter < 0)
{
Serial.println("Balloon is at minimum");
fadeCounter = 0;
//stop motor
analogWrite(MOTORPin, fadeCounter);
//next State
mState = WAITINGdown;
//restart the TIMER
commonTime = millis();
break;
}
}
}
break;
//======================== wait here for 15 seconds
case WAITINGdown:
{
//has the common TIMER expired ?
if (millis() - commonTime >= 15000ul)
{
Serial.println("Balloon sequence has ended");
//restart the automatic TIMER
automaticTime = millis();
//next State
mState = STARTUP;
break;
}
}
break;
} //END of switch/case
} //END of checkMachine()
// c h e c k S w i t c h e s ( )
//================================================^================================================
void checkSwitches()
{
byte state;
//======================================================================== buttonPin
state = digitalRead(buttonPin);
//================================================
//has this switch changed state ?
if (lastButtonState != state)
{
//update to the new state
lastButtonState = state;
//========================
//if the balloon is stopped, has the switch been pressed ?
if (mState == STARTUP && state == PRESSED)
{
Serial.println("Balloon is going up");
fadeCounter = 0;
//restart the TIMER
commonTime = millis();
//start the sequence for going up
mState = BALLOONup;
}
} //END of this switch
//======================================================================== nextSwitch
} //END of checkSwitches()
You need a "dummy" load to draw the minimum current that will keep the charger from shutting off. Do you have some resistors in the 100 to 220Ω range and an NPN transistor like 2n2222, 2n4401, 2n3904 or a spare N channel logic level MOSFET?
LarryD,
Thank you for that. It is a lot more advanced than my first code (which was my very first attempt at code). I will try this today. Is the total time after ramp down 30 seconds? I guess I will test.
Here is the schematic and wiring. Thanks
If that is your YouTube video the MOSFET looks it can be controlled by the 5v Arduino, good.
You should add the MOSFET and fan circuit to your drawing.
The sketch offered you in post number 2 (two) should be close to what you ask for, it can be easily change to accommodate your needs.
The heartbeat LED toggles ON every 1 second.
For testing, you can time things by counting the number of toggles.
Use the Serial Monitor set to 115200 with timing enabled.
You should see the progression printed on the serial monitor.
As mentioned, the power bank needs a minimum load current. @JCA34F
A second MOSFET controlling current to a 100 ohm resistor can be operated once per 45 to 55 seconds (ON for a second) . This will keep the power bank from turning OFF.
Thanks again. The code works great. There is a 45 second lag after the motor shuts off (15 seconds motor idle + 30 second delay) and that is fine. I don't think I will need to add a second mosfet to keep the battery enabled, but I can see where that would be beneficial in some cases. I have also been using the old bootloader and didn't in this case. What is the difference?
What is the serial.println for? Is that for a small OLED? That sounds cool. Someone suggested I add Close encounters of a third kind music tones.
This project started from an old Johnny Astro I use to own and I decided to add it to our Area 51 Train Layout for the kids so they could push a button to control the balloon. The fan has to ramp up and ramp down to keep pressure on the balloon so that it stays in the column. The frisbee was an afterthought to keep the balloon above the fan.
Thanks again for your help. I need to learn this stuff.
You should be aware this sketch version allows things to happen at the same time.
The sketch does not use delay( . . . ) hence it is non blocking.
Always write your sketch in a non blocking fashion.
If you do not ask questions, you will not learn anything.