But it is working as intended. And now that I know how it should be made, the prototype will probably stay with me for a loooong time!
Basically it is an ATtiny getting inputs from a selector with a row of 1k resistors to select mode (I am supposed to call it a "multi-resistor potential divider"), and 2 potentiometers to select timing and intensity.
The signal from the micro-controller goes to a MOSFET and from there to whatever motor you want to control.
Of course the signal could also be sent to an SSR to control an AC motor with some serious power, but PWM and AC is not an easy game, and would need some rewriting of he code.
The power is 9V sent through a 7805 to give 5.0V (must be nice voltage, otherwise the mode selection gets funny) and a separate battery pack to run the motor. It will control a rather large DC motor without problems.
I tried using the same power supply for motor and controller in the beginning, but it gave a lot of noise problems (resetting/tilting the controller with some motors) and limited the possibilities regarding how high a voltage could be supplied to the board.
Should you use an arduino, you can use the 5V connection on that instead of the 7805, to deliver the voltage to the the selector.
(But part of the fun was making something work with the ATTiny)
The setup uses 5 pins:
Analog read of selector
Analog read of time setting
Analog read of intensity setting
Analog write (PWM) to control the motor
Digital write to blink the status LED
Furthermore I added a reset button. It is still nice to have, but not really needed after I solved the noise problems that would tilt the controller.
The sketch:
The signal for the MOSFET is called "led", and "led2" is a stand-by indicator.
I started out controlling LEDs to see if it worked, and the name stuck.
(It could actually make a nice bicycle light)
Code: Select all
/* Motor controller by Sir Cumference.
Feel free to use it for your own pleasure (and the pleasure of whoever else is similarly inclined).
Developed on an arduino UNO, then transferred to an ATTiny85.
A lot of "Serial.print" is commented out in the code. If you use an arduino, it is nice to see what happens, but an ATTiny doesn't like the serial monitor.
Modes:
0: Stand by. led2 will blink to show stand by.
1: Constant on. Power is set by intPot
2: 1:3 Pulse/off. Power is set by intPot, time by timePot. Pauses are three times as long as pulses
3: 1:1 Pulse/off. As above, but 1:1 pulse:pause
4: Sinus. Sounds like an air raid siren! From 0 to max and back again. timePot decides how fast.
5: Sawtooth. Ramps up to the value set by intPot, then cuts off. TimePot decides how steep the ramp is.
*/
int led = 1; // was Arduino pin 11
int led2 = 0; // was Arduino pin 13
int selector = 1; //A0
int timePot = 2; //A1
int intPot = 3; //A2
int brightness4 = 0; // how bright the LED is in fade mode 4
int brightness5 = 0; // how bright the LED is in fade mode 5
int fadeAmount = 5; // how many points to fade the LED by in mode 4
int fadeAmount5 = 5; // how many points to fade the LED by in mode 5
int mode;
void setup()
{
// Serial.begin(9600);
pinMode(led, OUTPUT);
pinMode(led2, OUTPUT);
}
void loop()
{
// read values (and print for debugging)
int selectorVal = analogRead(selector);
int timeVal = analogRead(timePot);
int intVal = analogRead(intPot);
/*
Serial.println(selectorVal);
Serial.print("timeVal:");
Serial.println(timeVal);
Serial.print("intVal:");
Serial.println(intVal);
Serial.print("Mode:");
Serial.println (mode);
Serial.println("***********************");
*/
// determine mode
mode = 0;
if ( 100 < selectorVal )
{ mode = 1; }
if ( 300 < selectorVal )
{ mode = 2; }
if ( 500 < selectorVal )
{ mode = 3; }
if ( 700 < selectorVal)
{ mode = 4; }
if ( 900 < selectorVal )
{ mode = 5; }
// and use the mode determined
switch (mode)
{
case 0: // double blink to show stand by
digitalWrite(led, LOW); // bugfix.... if left high from another mode
digitalWrite(led2, HIGH); // turn the LED on
delay(100); // wait for a moment
digitalWrite(led2, LOW); // turn the LED off
delay(100); // wait for a moment
digitalWrite(led2, HIGH); // turn the LED on
delay(100); // wait for a moment
digitalWrite(led2, LOW); // turn the LED off
delay(2000); // wait for 2 seconds
//Serial.println("Stand By!");
break;
case 1:
//Serial.println("Constant on");
analogWrite(led, intVal/4); //just switch on in interval 0-255
//delay(1000);
break;
case 2:
//Serial.println("On-Off 1:3");
analogWrite(led, intVal/4); //on
delay(timeVal*5); //stay on for 5*timeVal
analogWrite(led, 0); // off
delay(timeVal*15); // off for 15*timeVal
break;
case 3:
//Serial.println("On-Off 1:1");
analogWrite(led, intVal/4); //on
delay(timeVal*5); //stay on for 5*timeVal
analogWrite(led, 0); // off
delay(timeVal*5); // off for 15*timeVal
break;
case 4:
//Serial.println("Sinus");
analogWrite(led, brightness4); // set the brightness of led:
brightness4 = brightness4 + fadeAmount; // change the brightness for next time through the loop:
// reverse the direction of the fading at the ends of the fade:
if (brightness4 == 0 || brightness4 == 255)
{
fadeAmount = -fadeAmount ;
}
delay(timeVal+1); // wait to see the dimming effect
break;
case 5:
//Serial.println("sawtooth");
// brightness5 = abs(brightness5);
analogWrite(led, brightness5); // set the brightness of led:
brightness5 = brightness5 + fadeAmount5; // change the brightness for next time through the loop:
delay(timeVal+1); // wait to see the dimming effect
if (brightness5 >= intVal/4) // give a short blink to show "end of tooth"
{
brightness5 = 0 ;
digitalWrite(led2, HIGH); // turn the LED on
delay(100); // wait for a moment
digitalWrite(led2, LOW); // turn the LED off
digitalWrite(led, LOW); // turn the LED off
delay(2000);
}
break;
}
delay(5); // for stability
}