Driving the H-bridge controller from the AVR

ian – Tue, 2006 – 07 – 04 12:15

The following code will test that the AVR and H-bridge driver are communicating properly. It assumes that there's an H-bridge and motor attached to PWM channel 0. It will run the motor at full power in one direction, then reverse the direction every few seconds. As I soon found out, this is a pretty tough on the hardware. This is intended for the ATMega32. I'm using WinAVR for compilation.

#include < avr/io.h>
#include < avr/interrupt.h>
#include < util/twi.h>

typedef unsigned char uchar;

void delay_ms(unsigned char ms)
/* badly mangled delay_ms */
{
unsigned short outer1, outer2;
outer1 = 1;

while (outer1) {
outer2 = 1000;
while (outer2) {
while ( ms ) ms--;
outer2--;
}
outer1--;
}
}

void wait_a_bit(void)
{
int i;

for (i = 0; i < 150; i++)
delay_ms(0);
}

void led_mid(void)
{
OCR1A = 80;
}

void led_off(void)
{
OCR1A = 0;
}

void led_on(void)
{
OCR1A = 255;
}

void twi_init(void)
{
// set TWI clock rate
TWSR |= 3; // div by 64
TWBR = 4; // div by another 3
// final clock rate should be about 10kHz

/*set initial state of TWCR
FIXME stub*/
}

void debug(uchar val)
{
PORTA = val;
}

uchar twi_write_byte(uchar addr, uchar data)
{
// I-bit in SREG must be set

// write to TWCR to start transmission: TWINT 1, TWSTA 1, TWSTO 0, TWEN 1
TWCR = (1 << TWINT | 1 << TWSTA | 1 << TWEN);

while (!(TWCR & (1 << TWINT)))
;

if (((TWSR & 0xf8) != TW_START) && ((TWSR & 0xf8) != TW_REP_START)) // added by Ian; repeated START is OK
return 1; // error

TWDR = (addr << 1) | TW_WRITE;
TWCR = (1 << TWINT) | (1 << TWEN);

while (!(TWCR & (1 << TWINT)))
;

if ((TWSR & 0xf8) != TW_MT_SLA_ACK)
return 2; // error

TWDR = data;
TWCR = (1 << TWINT) | (1 << TWEN);

while (!(TWCR & (1 << TWINT)))
;

if ((TWSR & 0xf8) != TW_MT_DATA_ACK)
return 3; // error

TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWSTO);
while (!(TWCR & (1 << TWSTO))) // Ian's addition: make sure STOP condition has finished
;

return 0;
}

void debug_init(void)
{
DDRA = 0xff;
}

void wait_fast(void)
{
int i;

for (i = 0; i < 30; i++)
delay_ms(0);
}

int main(void)
{
int err = 0;

/* enable PD5 as output */
DDRD |= 1 << PD5;

/* set up the PWM */
TCCR1A |= 1 << COM1A1; // clear OC1A/OC1B on compare match during upcount; set on match during downcount
TCCR1A |= 1 << WGM10; // PWM, phase correct, 8-bit
TCCR1B |= 1 << CS10; // internal clock, 1:1 prescale

/* we want to set the LED to mid brightness during init, then set it to full-on if i2c transmit is successful, full-off otherwise */

debug_init();

led_on();
debug(0xff);
wait_a_bit();
led_mid();
debug(0x0);
wait_a_bit();

twi_init();
/*
; The truth table for the output is:
; Reverse Brake | A B C D
; --------------+--------
; 0 0 | P 0 0 P
; 0 1 | 0 0 P P
; 1 0 | 0 P P 0
; 1 1 | 0 0 P P

twi_command:
; command format: 8 bits
; ccdbssss
; cc = channel number. Only the LSB is used on this device.
; d = direction. 0 forward, 1 backwards
; b = brake. 0 no brake, 1 brake
; ssss = speed. higher values -> higher speed
*/

int speed = 0;
int count = 0;
int dir = 0;

while (1) {
dir = ~dir;

//if (dir)
// speed++;

speed = 0xf;

int addr = 0b1000000;
int data_base = 0b00000000;
int data = data_base | (speed & 0xf) | (dir & 0b00100000);
debug(1);
err = twi_write_byte(addr, data);

debug(data);

/* want to send the command '01001010' to address '1100000' as a write */
//err = twi_write_byte(0b1000000, 0b01111010); // 2/3 brake port 1
//wait_a_bit();
//err = twi_write_byte(0b1000000, 0b00001000); // 1/2 fwd port 0

//err = twi_write_byte(0b1000000, 0b01111010); // 2/3 brake port 1
//err = twi_write_byte(0b1000000, 0b00101010); // 2/3 back port 0
//err = twi_write_byte(0b1000000, 0b01101010); // 2/3 back port 1
//err = twi_write_byte(0b1000000, 0b01001010); // 2/3 forward port 1

if (err) {
while (1) {
led_off();
debug(err);
wait_a_bit();
led_on();
debug(TWSR);
wait_a_bit();
}
} else {
led_on();
}

//debug(speed);
wait_a_bit();
wait_a_bit();

}

return 0; // we should never hit this
}


Reply

Please solve the math problem above and type in the result. e.g. for 1+1, type 2
The content of this field is kept private and will not be shown publicly.
  • Allowed HTML tags: <a> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd>
  • Lines and paragraphs break automatically.
More information about formatting options