I have a small project in which I need to create an agitator for a tiny amount of liquid in a vial, and it needs a 5 minute timer on the agitation cycle. I will be building the item which holds the vial itself in my 3d printer, but I was thinking of taking a small brush motor (came in my little starter kit a long time ago, no details on it, body is about 25mm long, shaft is 2mm) and affixing a very small metal (likely will go with brass) eccentric to it, to basically just make it vibrate, and then attaching the motor to the 3d printed arduino housing, with the vial holder affixed to that, so that you press a button, the whole thing vibrates for 5m, then shuts off. My problem is, I just went with the blink program, added a button, (pullup pin 2) changed the 'LED' (motor) output to pin 9, gave it a delay variable of 300000ms (should be ==5m) and uploaded it, I then removed board from pc usb connector, connected the board to a wall wart with a 6v 2A output, via the round jack on the board, and when I press the button the motor seems to do fine for approximately 20 seconds, then slows briefly, then resumes beginning rpm, and makes it to about 1 minute, then stops altogether. Is there a better sample program I could be using to accomplish this task and get more consistent running of the motor for the full 5 minutes? The current code I tried is as follows:
/*
Blink
Turns an LED on for one second, then off for one second, repeatedly.
Most Arduinos have an on-board LED you can control. On the UNO, MEGA and ZERO
it is attached to digital pin 13, on MKR1000 on pin 6. LED_BUILTIN is set to
the correct LED pin independent of which board is used.
If you want to know what pin the on-board LED is connected to on your Arduino
model, check the Technical Specs of your board at:
https://www.arduino.cc/en/Main/Products
modified 8 May 2014
by Scott Fitzgerald
modified 2 Sep 2016
by Arturo Guadalupi
modified 8 Sep 2016
by Colby Newman
This example code is in the public domain.
http://www.arduino.cc/en/Tutorial/Blink
*/
const int buttonPin = 2;
// the setup function runs once when you press reset or power the board
void setup() {
pinMode(buttonPin, INPUT_PULLUP);
// initialize digital pin LED_BUILTIN as an output.
pinMode(9, OUTPUT);
}
// the loop function runs over and over again forever
void loop() {
while (digitalRead(buttonPin)) {}
digitalWrite(9, HIGH); // turn the LED on (HIGH is the voltage level)
delay(300000); // wait for a second
digitalWrite(9, LOW); // turn the LED off by making the voltage LOW
delay(1000); // wait for a second
}
Agreed. Sounds like it could be an overheating problem, or a brown-out reset problem or some other hardware thing. We need to see exactly how you wired everything and every component you used (or should have used but haven't).
Ok I actually tried something different, and it gets rid of the speed up, slow down, speed up problem, but it still doesn't function exactly how I want. In this sketch, it works perfectly, up to return 0; where I was hoping that it would go back to the button read, but it doesn't, it just continues running constantly. I also switched to a 9v alkaline power source connected to the round plug. But after seeing the motor not stay a steady speed I felt that perhaps a potentiometer added to the equation would not be a bad idea, so I can adjust the amount of vibration, in theory, but it does not properly time the motor on/off as I would like. I'm not the greatest at schematics, but I can take a picture of the setup and upload it momentarily. Here is the second code i am trying to use now, just with the issue of it not turning off at the return 0; command. Any suggestions on how I can fix that would be great. Thanks!
//control motor with 2222 transistor and potentiometer
const int buttonPin = 2;
int potPin = 0;
int motorPin = 5;
int potVal = 0;
int motorSpeed = 0;
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
pinMode(buttonPin, INPUT_PULLUP);
pinMode(motorPin, OUTPUT);
pinMode(potPin, INPUT);
}
void loop()
{
while (digitalRead(buttonPin));
{
// put your main code here, to run repeatedly:
potVal = analogRead(A0);
Serial.print("potvalue");
Serial.println(potVal);
motorSpeed = map(potVal, 0, 1023, 0, 255);
Serial.print("motorSpeed");
Serial.println(motorSpeed);
analogWrite(motorPin, motorSpeed);
delay (5000);
}
return 0;
}
I honestly don't know haha. I read on another forum that I can get the loop to reset by adding return0; after, and it obviously didn't work with the rest of my code.
We can probably tell you. But in order to do that...
daveyg1987:
I read on another forum that I can get the loop to reset by adding return0
You misunderstood. Or they did. Or they didn't really care what they told you...
You can end loop() with a return statement. But not from within a function called from loop(). That would just end that function. Either way, its generally considered poor programming practice.
The other forum was just an old post on a similar topic. In any case, I still have not figured out how to accomplish my task. I've started messing with millis() programming, but still not getting consistent results. It kinda works, as long as it is connected to the pc, but the time is off by half, I set in this program to run for 30000 ms, which should equate to 30s, but it only actually runs the motor for 15s, if I try to use my 6v 2a power supply, it will give me a couple of short bursts of motor movement, like 1s on, 1s off, 1s on, then waits until button is pressed again.
//Global Variables
const byte BUTTON=2; // our button pin
const byte motorPin=9; //pwm output to 2222 transistor
unsigned long buttonPushedMillis; // when button was released
unsigned long ledTurnedOnAt; // when motor was turned on
unsigned long turnOnDelay = 500; // wait to turn on motor
unsigned long turnOffDelay = 30000; // turn off motor after this time
bool ledReady = false; // flag for when button is let go
bool ledState = false; // for motor is on or not.
void setup() {
pinMode(BUTTON, INPUT_PULLUP);
pinMode(motorPin, OUTPUT);
digitalWrite(motorPin, LOW);
}
void loop() {
// get the time at the start of this loop()
unsigned long currentMillis = millis();
// check the button
if (digitalRead(BUTTON) == LOW) {
// update the time when button was pushed
buttonPushedMillis = currentMillis;
ledReady = true;
}
// make sure this code isn't checked until after button has been let go
if (ledReady) {
//this is typical millis code here:
if ((unsigned long)(currentMillis - buttonPushedMillis) >= turnOnDelay) {
// okay, enough time has passed since the button was let go.
analogWrite(motorPin, 150);
// setup our next "state"
ledState = true;
// save when the LED turned on
ledTurnedOnAt = currentMillis;
// wait for next button press
ledReady = false;
}
}
// see if we are watching for the time to turn off LED
if (ledState) {
// okay, led on, check for now long
if ((unsigned long)(currentMillis - ledTurnedOnAt) >= turnOffDelay) {
ledState = false;
digitalWrite(motorPin, LOW);
}
}
}
This is a poor drawing in paint of my current wiring schematic. Currently I am getting a motor run time of anywhere from 6s to 1m, with the delay set to 300000 (5m)
Your button is connected correctly. Everything else is wrong and could damage the Arduino.
The 3.3V pin on the Arduino is not suitable for powering a motor. What voltage range can your motor be used with? Powering it directly with 6V from the PSU would be better, if that's possible. The transistor should be between the motor and ground. There should be a current limiting resistor between the transistor base and the Arduino pin, eg. 1K. The diode should be in parallel with the motor connections, with is anode toward the transistor.
I actually picked the 3.3v out by trial and error, it gives me the most consistent (albeit slow) motor run time. I started out with it connected to the vin output, with a 9v battery or 6v 2a power supply plugged in, and it worked, but not well, and killed the 9v alkaline very quickly, the 6v 2a wall wart seems the most finicky and erratic, then I tried the 5v out, worked but not great, the 3.3v out, although dangerous seems the most stable. As stated previously, there is no data whatsoever with the motor, just came in one of the cheap arduino starter kits, I think it is 12v rated, just a guess though. I will try it the way you show there. I currently have a diode in there but it is just running in-line with the + between the transistor and motor, I will switch it to the location in your schematic and report back. Thank You!
Ok so with the motor connected with the diode between the motor - and +, with the stripe (anode) toward the + side, and the 6v 2a wall wart connected, and connected via USB, it works properly, but only with a run time of 10 seconds. If I disconnect the USB I get the same 10s of run time. Connected to the 3.3v output, if I move the + from the transistor to the vin output, I get very erratic motor run, where it goes up to speed for about 1s then drops, then ramps back up, then drops, then back up, in 1s increments. If in the 5v out position, it runs for only 2s, but without any drops and peaks, just on, 2s, off. This makes me think that perhaps the 6v2a input is not enough, so it works a little longer when the output is metered down to 3.3v, but if in the 5v or vin (6v theoretically) then it draws too much and causes issues.
Here is the current program, again, I am open to suggestion if there is a better base program to use:
const byte BUTTON=2; // our button pin
const byte motorPin=9; //pwm output to 2222 transistor
unsigned long buttonPushedMillis; // when button was released
unsigned long ledTurnedOnAt; // when motor was turned on
unsigned long turnOnDelay = 500; // wait to turn on motor
unsigned long turnOffDelay = 300000; // turn off motor after this time
bool ledReady = false; // flag for when button is let go
bool ledState = false; // for motor is on or not.
void setup() {
pinMode(BUTTON, INPUT_PULLUP);
pinMode(motorPin, OUTPUT);
digitalWrite(motorPin, LOW);
}
void loop() {
// get the time at the start of this loop()
unsigned long currentMillis = millis();
// check the button
if (digitalRead(BUTTON) == LOW) {
// update the time when button was pushed
buttonPushedMillis = currentMillis;
ledReady = true;
}
// make sure this code isn't checked until after button has been let go
if (ledReady) {
//this is typical millis code here:
if ((unsigned long)(currentMillis - buttonPushedMillis) >= turnOnDelay) {
// okay, enough time has passed since the button was let go.
analogWrite(motorPin, 150);
// setup our next "state"
ledState = true;
// save when the LED turned on
ledTurnedOnAt = currentMillis;
// wait for next button press
ledReady = false;
}
}
// see if we are watching for the time to turn off LED
if (ledState) {
// okay, led on, check for now long
if ((unsigned long)(currentMillis - ledTurnedOnAt) >= turnOffDelay) {
ledState = false;
digitalWrite(motorPin, LOW);
}
}
}
Works perfectly with an LED instead of the transistor and motor, push button, .5s later LED lights, 5m later LED dies. so I think my problem is definitely related to power draw, and possibly also a poor choice of program for this application as well.
Ok I have solved it. The latest program I uploaded works fine, I just needed to isolate the current for the motor. I still get some speed fluctuation (I'm assuming it is just voltage fluctuation from the alkaline battery, perhaps I will add a capacitor to try and buffer the motor speed) I put my 9v battery direct to the - of the motor (and jumpered to the gnd of the arduino) and the 9v + to the transistor, with the USB power or the 6v supply to the arduino it works perfectly, motor doesn't even heat up hardly beyond ambient over the 5m timer. My one and only complaint is having to use two separate power sources, maybe I will get a 12v wall wart for this project and incorporate a small power divider/isolator to send 5v and like 1A to the arduino, and send 12v 2A to the motor/transistor.
Woah, don't tell us about your complaints when you have ignored all the advice we have been giving you! Instead, you just keep trying random changes and getting random results, which we can't help with because we can't see what you are changing.
There's no need to use 2 power supplies if you connect everything correctly. Certainly not a 9V battery, those things are only useful for smoke alarms, not Arduinos.
Your 6V 2A PSU should be adequate to run the whole circuit. A 12V PSU is going to make things worse.
Sorry about that, I am quite ADHD, and as such I have zero patience, it is a poor excuse, but it is the only one I have. Ok so here is what I have now, and it is quite functional. However I would like very much to get away from using the 9v alkaline, and use just one power source, that can be attached to a 110v 60hz US wall outlet. Again, appologies for my poor schematic abilities. I hope that it displays properly that I have done as you suggested (at least as far as I understood it, if I put something in the wrong place, or still need to add something, please let me know)
If I were to use just the 6v 2A supply, would I need to splice into the wire before it goes into the arduino, for the transistor, or can I attach the input of the transistor to the vin pin of the arduino without issue, now that I have the diode and resistor in the correct location?
No. Look at the diagram in post #11. The 2n2222 is an npn transistor. It should be used to switch on the "low side" of the load. The load is the motor. That means the transistor is between the load and ground, not between the load and +V.