Turning a spinning wheel electric

ruthcatrin:
This is an odd little store. Looks for all the world like someone's (huge) backroom stash got turned into a store. Very helpfull fellows though. Otherwise though I was unable to find any electronics stores. Or rather, when I do that search I get Best Buy, and other such stores, which isn't helpfull.

I know what you mean. Since I do a lot of this stuff, it's sort of easier because I just buy bulk, from a large seller. If I get below 10 or 20 of something, I add them to my next order. ('RS Components' are my favourite - free courier delivery for online orders, regardless of the size of the order.)
For modules etc, I buy from eBay, but make sure I have a few projects happening concurrently and just put one aside until things arrive and work on another.

Ok, I got called into work yesterday and today, and its hard to say no when I'm otherwise only scheduled for one day....

So, rewired, but I haven't yet checked with prong is which on the power switch, so I wired per your diagram. As before: didn't hook up the battery or fuse or motor, and the MOSFET and diode don't fit on the board.

One question, looking at that, there doesn't appear to be a jumper to a pin for the on/off switch?

Ok, two, I connected to the ground on the Arduino using the ground on the same side as the A-pins, does it make a difference?

Ok, so based on that, not counting the pin for the on/off:

const int buttonPin = ??;        // on off button
const int batteryPin = A1;      // battery
const int motorPin = 3;         // motor
const int ledPin = 2;           // status led for battery

const byte potPin = A0;      //throttle pot

int buttonState = 0;            // push button status

int potVal;

void setup()
{
    pinMode(ledPin, OUTPUT);
    pinMode(buttonPin, INPUT_PULLUP);
    pinMode(batteryPin, INPUT);     
    pinMode(motorPin, OUTPUT); 
}

Now, does

potVal=analogRead(potPin);

go into the setup loop?

ruthcatrin:
One question, looking at that, there doesn't appear to be a jumper to a pin for the on/off switch?

I mentioned that in a reply the other day. You don't want the Arduino reading the main power switch. That would mean that the Arduino would have to already be powered, to be able to read the switch. As I wired it, the switch powers up everything at once, and isolates the battery completely when it's off.
Otherwise, you'd need to disconnect the battery every time you turn it off, as well as throwing the power switch.

Ok, two, I connected to the ground on the Arduino using the ground on the same side as the A-pins, does it make a difference?

All 'GND' connections on the Arduino are connected together, so it doesn't matter which you use.

The MOSFET should fit in the breadboard. Just wriggle it a bit as you push it in.
The diode can be soldered directly across the motor terminals. That's the best place for it anyway - as close to the motor as possible.

It's a good idea to connect the fuse before any testing. You just need to solder it in series with the positive battery lead.

I have to mow the lawns etc right now, but I'll check out your pics a little later on and post another reply.

Aha! You did say that, sorry. Went to type programming and forgot.

I've had a chance to look over your photos now Ruth.
Overall, the wiring looks good, and is all correct. A couple of points concern me though:-

In this shot, it looks like there's a chance that the right-hand-side switch terminal could short with the wire leading to the positive rail on the breadboard. (Circled.) I'd personally use longer wires to the switch, so it's clear of the breadboard.
Potential switch short.jpg

And similarly in this shot, it looks like the two wires in the circle could potentially short together, and possibly also the yellow and white wires just to the left.
Maybe trimming off the ends of some wires would be a good idea, so there's no bare wire extending out of the UNO and breadboard socket holes.
Potential UNO short.jpg


Something else that concerns me is the fact that the wires are only bent around the terminals on the switch, pot and diode. I assume that's temporary, but they will need to be soldered before power can be applied to the circuit. Solder them in such a way that they can be unsoldered when it comes to building the final version on veroboard, after testing on the breadboard. (When you solder the temporary connections, avoid looping the wire around things, or it'll be hard to unsolder. Just tin both and solder the connections flat, if you get what I mean.)

Also, it's fairly important that you connect the fuse up when you do connect the battery, and be very careful that the battery is connected in the correct polarity, or a couple of parts will go pop and let their magic smoke out. (Not a good thing. :frowning: )
Don't power up just yet though, until the code is written and I've had a peek at it.


Now to that code. The parts relating to the buttonPin aren't needed now of course. Also, in 'setup()', there's no need to initialise the 'motorPin' as 'OUTPUT' - that's done automatically when you call 'analogWrite()'.
The same goes for 'batteryPin' and 'potPin'. They're automatically set up when you call 'analogRead()'.
So the only pin that needs to be set up in 'setup()' is 'ledPin'.
Removing those parts from the code you posted, it would look like this:-
(Oh, I made all the pin allocations 'byte' too.)

const byte batteryPin = A1;      // battery
const byte motorPin = 3;         // motor
const byte ledPin = 2;           // status led for battery
const byte potPin = A0;          // throttle pot

int potVal;

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

I know you want to write your own code, so I won't show it to you, but I've already written (my version of) the program and am currently putting together a test circuit so that I can test your program when you get it written.


Most of the program is fairly straightforward, but when you write the part that reads the battery voltage, it needs to set the LED "HIGH" if the analogue value is below 868, or set it "LOW" if the analogue value is above 872. That equates to 11.9V +/- 28mV, for a total of 56mV hysteresis. (Those values might need to be fine-tuned later, but they're good starting points.)

And when you write the pot/motor code, don't forget that after reading the pot, you need to divide the result by 4 before using 'analogWrite()' to generate the PWM for the motor. This converts the analogue 0-1023 value to 0-255 for the 8-bit PWM.

I think I've covered everything important.

Edit: Nope, I forgot to say - don't forget to test the switch and check on which terminal is which.

Gonna check the switch today. And yup, I'll make sure the fuse is in before wiring in the battery. And yup, I just bent in the wires on the switch and the pot for the sake of holding them there while I took the picture, I do understand what you're saying about soldering them in before adding power (and I'll lengthen the ones on the switch and fix the other spots where they're touching). But cool!

I can verify that the circuit works fine now. I tested it earlier with my version of the program, and it works well, without a hitch.
As mentioned, the battery monitoring threshold and hysteresis might need tweaking. Because the battery-sensing resistors have 1% tolerance, there can be about 0.1V variation in the threshold, but that varies from resistor to resistor, of course.

Edit: In my circuit, I found that a threshold of 872 was best, with hysteresis of +-4, but we'll wait and see.....
(I used a different battery, 12V 1.4Ah, different motor and of course, different resistors.)

Ok, checked the switch. The "+" (the outside prong) is the power in, and the "A" (the middle prong) is the power out.

Ok, lemme see if I have the concept order correct for programming.

I need it to turn on with the switch, which if I understand correctly I don't need to program in? It'll just do it if I've wired it right?

1: It needs to read battery state and turn on the LED if the battery is low.

2: It needs to read the throttle pot's state and control the speed of the motor based on it

cycle 1 & 2 till I turn it off?

Ok, either this is the easiest code I've ever written or I've seriously screwed up somewhere.....

Question, some of the examples I'm finding of using a pot to control the motor include:

Serial.begin(9600);

in the setup loop, but only some?

What I've got so far:

const byte batteryPin = A1;      // battery
const byte motorPin = 3;         // motor
const byte ledPin = 2;           // status led for battery
const byte potPin = A0;          // throttle pot

int potVal;

void setup()
{
    pinMode(ledPin, OUTPUT);
}
void loop() {
  int batteryADC = analogRead(batteryPin);    // Read the analogue pin.
    if (batteryADC >= 872)                    // Compare with upper threshold.
        digitalWrite(ledPin, LOW);            // Battery OK - turn the warning LED off.
    else if (batteryADC <= 868)               // Compare with lower threshold.
        digitalWrite(ledPin, HIGH);           // Battery low - turn the warning LED on.

   potVal=analogRead(potPin);
   byte pwmVal=potVal/4;     
   analogWrite(motorPin, pwmVal);
}

Do I need to program in a delay of any kind anywhere? I'm thinking not, cause I want both of these functions to trigger as soon as there's a state change.

Have you run this code yet ? What is the result ?

raschemmel, you do realize that the forum sends me the ORIGINAL version of your post?

Yeah, actually I forgot about that.
That was a mistake on my part. I misread your code. Sorry about that.
I sort of jumped the gun. So how is it going ? Is the code working ?

I haven't run it yet. 1-I'd like someone to tell if it looks reasonable or not, as I said above either this is the simplest coding I've ever done or I've screwed it up big time....... 2-today's the day my Husband and I usually spend the day doing household chores and I haven't had time to do the soldering so that the connections are solid. And unfortunately I probably won't have time tomorrow as I actually have to work (horrid thing when you need a paycheck!).

I can't find the Reply that has your schematic so I don't know how you wired it. What you are trying to do is dirt simple. While software is not my area of expertise (I'm H/W), one thing did catch my eye and that's the absence of a Map function in your code.
Anytime you are reading a pot for the purpose of using it as a front panel control know, it is almost ALWAYS useful to use the Map function. I'm not saying it's necessary but usually it gives you more control. Without knowing what your battery's nominal voltage is I don't know it I should mention this but
FYI, in case you didn't know, the ADC analogRead values are based on the analogReference, which, is [DEFAULT], (5V) since you haven't changed it. That means that if your battery dropped BELOW 5V, your readings would no longer be accurate so usually there is some steps taken to prevent that (in the hardware) or you put something in the code that lights a led to indicate that the reference is no longer valid and any readings are wrong.

Do I need to program in a delay of any kind anywhere?

How fast can your eyes detect light ? Without any delay, your led can turn on for a fraction of a second when it is at the threshold and you would NEVER see it UNTIL the duty cycle of the led On time to OFF time surpasses the minimum threshold of your eye/brain to detect light.
So to answer your question, yes you need SOME delay, at the very minimum 300 mS but I would probably opt for 500mS or more. Without the schematic, I have no idea what is powering the motor but if your battery is powering the motor and you turn on the motor, the battery voltage will immediately be pulled down by the motor. If your code then detects the voltage is too low, your code should turn OFF the motor , but then the voltage will jump back UP, and the code will tell the motor to turn ON, pulling the battery voltage DOWN (AGAIN) , at which time the code will detect the voltage is too low and turn the motor OFF , at which time the voltage will jump back UP again....

Do you see where I am going with this ?
How would you change the code to prevent it ?
Hint: Another thing that caught my eye was the absence of any boolean flags .
Are you familiar with how those might relate to your project ?
Let's pretend there is NO uP and NO code , but simply humans, with flags in there hand.
There's one guy who does nothing but watch the battery voltage and when it gets too LOW, he raises a red flag and MUST keep it raised until the foreman (the CPU) tells him he can relax (clear the flag).
There's another guy who does nothing but control the power to the motor. He doesn't care what speed it is going . He is only interested in ON/OFF status. If the foreman tells him to turn the motor OFF , he does so and raises a red flag (motor off flag). The guy who controls the speed doesn't care about anything else and he has no flags. Once the voltage drops below the threshold , that flag goes up, and the foreman sees it and tells the other guy to "SHUT DOWN THE MOTOR !) at which time that guy raises his red flag. Now you got two guys holding flags up and the motor is stopped. What would the foreman do now ?
If you had a relay controlling the connection to a charger , you could energize the relay and charge the battery until the voltage was high enough and then shutdown the relay until the next time both red flags were up.

FYI, yes I know your motor state is not controlled by your battery voltage. I was just using that as an example.
Is there a voltage divider for the battery ? 872 analog counts corresponds to 4.2V . Is the analog pin connected to the battery or the center of a voltage divider ? what does 872 analog counts correspond to ?

Ruth, no problem. It works fine. Looks almost identical to what I wrote. (And I thought you'd make at least one mistake.)

@raschemmel, I disagree about adding a delay. There's no need for one at all. And there's no need for 'map()', although it could be used.
When doing a simple mapping between 0-1023 and 0-255, dividing by 4 is fine, and gives the same result.

And no need for flags or anything since, as you yourself point out, the motor isn't prevented from running when the battery is sensed to be low. It's just a reminder, in case the spinning wheel is used for too long in one burst and the battery begins to get a bit low.

Sometimes simple is best - no need to overcomplicate things for no reason. I only did two things differently in my version, and neither changes operation at all. I used defines for the threshold and hysteresis values, out of habit, and incorporated the last two lines of Ruth's code into one, so my version is 7 lines long whereas her's is 8. Virtually indentical.

So you're good-to-go, Ruth.

Here's my version of the code. (Almost twins):-

/* SpinningWheelController.ino
*
*  Processor - UNO
*  Notes:-
*  Controls the speed of a spinning wheel driven by a 12VDC geared brush motor
*  and powered by a 12VDC 7Ah lead-acid battery.
*  Reads a 10K pot to determine speed, and also monitors the battery voltage
*  via a voltage divider and lights a "low battery" LED if the voltage falls
*  below 11.9V.
*/

// Defines:-
#define BATT_THRESHOLD 870                                  // 11.9V threshold.
#define BATT_HYSTERESIS 2                                   // 56mV hysteresis, (+/- 28mV).

// Pin allocations:-
const byte potPin = A0;                                     // Throttle pot input.
const byte batteryPin = A1;                                 // Battery voltage sampling input.
const byte ledPin = 2;                                      // Status LED for battery.
const byte motorPin = 3;                                    // Motor PWM output.

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

void loop()
{
    // Check battery status - light LED if the battery voltage is below 11.9V:-
    // (56mV hysteresis.)
    int battVal = analogRead(batteryPin);                   // Read the battery voltage.
    if(battVal <= BATT_THRESHOLD - BATT_HYSTERESIS)         // Check if it's low and
        digitalWrite(ledPin, HIGH);                         // if so, light the LED.
    else if(battVal >= BATT_THRESHOLD + BATT_HYSTERESIS)    // Else check if it's OK and
        digitalWrite(ledPin, LOW);                          // if so, turn off the LED.

    // Read the throttle pot and set the motor speed:-
    int potVal = analogRead(potPin);                        // Read the pot, scale the value
    analogWrite(motorPin, potVal / 4);                      // from 0-255 and set motor speed.
}

raschemmel, I just thought I'd better add - the reason no delay is really needed is that if the LED only lights for a tiny fraction of a second, too short for the eye to see, the battery isn't yet low enough to worry about.
With or without without a short delay, it will flicker a little as it nears/crosses the threshold, due to load variations. That's the point where it's reminding the user that it's getting close to time to charge. When the LED lights constantly, it's definitely time to shut down and head for the charger.

Ruth, ideally a lead-acid battery likes to be kept fully charged, so always charge it after use anyway, and try to avoid putting the wheel away without doing so, especially if it's been running for a while. The LED is really just a last warning that the battery is close to fully discharged.
If you always start with a fully charged battery, you may never see that LED light at all.

Edit: If you did want it to shut down completely when the battery is low, that's easy too, but the threshold would need to be raised, and the hysteresis value increased heaps, so it didn't cut in and out. (The lower trip point would stay the same, but the upper one would be higher.) Otherwise what would happen is that under load the voltage would go down, then when it's shut off, the voltage would rise again and it would cut back in, dropping the battery voltage and cutting out again etc etc. The hysteresis would have to be large to avoid that.

At this point no, I don't want it to shut off when the warning light goes on. If I change my mind in the future thats a programming change.

And cool, that makes Arduino programming one of the simplest things I've ever looked at. Ok, I'll see if I can get to soldering later today after work, but may not get to it till tomorrow, then a test run with the breadboard (and yes, I'll hook up the fuse before the battery!), and then I have to finish cutting the wood for the base to attach this all to the actual wheel......