I made a 12V dc motor controller using arduino uno board. This controller controls the speed and the direction of this motor. I used the library PWM.h to generate pwm signal, and I built the H-brige using 2 N-type mosfets and 2 P-type mosfets and some other transistors. The speed level is indicated by 7 leds connected to shift register. Also I used timer2 to interrupt every about 30ms in order to read the analog value and then generate the pwm signal and write the speed level.
The code and circuit are below:
#include <PWM.h>
unsigned char k=0, l=0, m=0, n=0;
int32_t frequency = 20000; //pwm frequency in Hz
int timer2_initial_value,s;
void setup(){
pinMode(0, OUTPUT);
pinMode(1, OUTPUT);
pinMode(11, OUTPUT);
pinMode(12, OUTPUT);
pinMode(13, OUTPUT);
pinMode(2, INPUT_PULLUP);
pinMode(3, INPUT_PULLUP);
pinMode(4, INPUT_PULLUP);
InitTimersSafe();
bool success = SetPinFrequencySafe(9, frequency);
// initialize timer2 interrupt for adc reading
noInterrupts(); // disable all interrupts
TCCR2A = 0;
TCCR2B = 0;
timer2_initial_value = 0;
TCNT2 = timer2_initial_value; // preload timer
TCCR2B |= (1 << CS22) |(1 << CS21) | (1 << CS20); // 1024 prescaler
TIMSK2 |= (1 << TOIE2); // enable timer overflow interrupt
interrupts(); // enable all interrupts
}
ISR(TIMER2_OVF_vect) // interrupt service routine
{
TCNT2 = timer2_initial_value; // preload timer
n++;
if (n>20){
n = 0;
k = 0;
if (s != analogRead(A0)){
s = analogRead(A0);
pwmWrite(9,s/4);
if (s > 950) l = 0;
else{ if (s > 850) l = 1;
else{ if (s > 720) l = 3;
else{ if (s > 600) l = 7;
else{ if (s > 480) l = 15;
else{ if (s > 350) l = 31;
else{ if (s > 150) l = 63;
else l = 127;}}}}}}
for(m=0;m<7;m++){ //send data serially to speed level via shift register
digitalWrite (12,bitRead(l,k));
digitalWrite (11,1);
digitalWrite (11,0);k++;}
}
}
}
int fwd(){
while(1){
digitalWrite(0,HIGH);
digitalWrite(1,LOW);
if (digitalRead(4)==0) break;}}
int pwd(){
while(1){
digitalWrite(0,LOW);
digitalWrite(1,HIGH);
if (digitalRead(4)==0) break;}}
void loop()
{
k = 0;
l = 127; //all 7 leds are off
digitalWrite(0,LOW);
digitalWrite(1,LOW);
digitalWrite(13, LOW);
if (digitalRead(2)==0) {digitalWrite(13, HIGH);fwd();}
if (digitalRead(3)==0) {digitalWrite(13, HIGH);pwd();}
for(m=0;m<7;m++){
digitalWrite (12,bitRead(l,k));
digitalWrite (11,1);
digitalWrite (11,0);k++;}
}
At last this is a video shows the working:
