- קוד: בחר הכל
#define F_CPU 20000000UL
#include <avr/io.h>
#include <util/delay.h>
// Initialize timer 0 to do PWM for our motors:
void pwm0_init(void)
{
// Set Timer Control Register 0 A for PWM on both OC0A and OC0B,
(mode 3):
TCCR0A = (2 << COM0A0) | (2 << COM0B0) | (3 << WGM00);
TCCR0B = (4 << CS00);
// We're in PWM mode, so no need of interrupts:
TIMSK0 = 0;
// Enable output on PD5 and PD6 so we get our PWM outputs on the
// LMB1836M motor driver inputs:
DDRD |= (1 << PD5);
DDRD |= (1 << PD6);
// Enable output on PB1 and PB2 so we can set those bits to get
// directional control on the other inputs on the LMB1836M:
DDRB |= (1 << PB1);
DDRB |= (1 << PB2);
// Set our waveforms to zero for the time being: (Zero speed.)
OCR0A = 0;
OCR0B = 0;
}
// Motor A uses PB2 and PD6
void pwm0_a(int speed)
{
if (speed > 0)
{
// Forward
// Turn off PB2
PORTB &= ~(1 << PB2);
// Clear compare mode for PWM0A and set to clear on compare
// match, set at bottom:
TCCR0A = (TCCR0A & ~(3 << COM0A0)) | (2 << COM0A0);
// Set our PWM duty cycle
OCR0A = speed;
}
if (speed == 0)
{
// Disconnect PWM from 0C0A:
TCCR0A &= ~(3 << COM0A0);
// Set outputs to zero to coast
PORTD &= ~(1 << PD6);
PORTB &= ~(1 << PB2);
// No PWM duty cycle to set
}
if (speed < 0)
{
// Reverse
// Turn on PB2
PORTB |= (1 << PB2);
// Clear compare mode for PWM0A and set to set on compare
// match, clear at bottom:
TCCR0A = (TCCR0A & ~(3 << COM0A0)) | (3 << COM0A0);
// Set our PWM duty cycle
OCR0A = -speed;
}
}
// Motor B uses PB1 and PD5
void pwm0_b(int speed)
{
if (speed > 0)
{
// Forward
// Turn off PB1
PORTB &= ~(1 << PB1);
// Clear compare mode for PWM0B and set to clear on compare
// match, set at bottom:
TCCR0A = (TCCR0A & ~(3 << COM0B0)) | (2 << COM0B0);
// Set our PWM duty cycle
OCR0B = speed;
}
if (speed == 0)
{
// Disconnect PWM from 0C0A:
TCCR0A &= ~(3 << COM0B0);
// Set outputs to zero to coast
PORTD &= ~(1 << PD5);
PORTB &= ~(1 << PB1);
// No PWM duty cycle to set
}
if (speed < 0)
{
// Reverse
// Turn on PB1
PORTB |= (1 << PB1);
// Clear compare mode for PWM0B and set to set on compare
// match, clear at bottom:
TCCR0A = (TCCR0A & ~(3 << COM0B0)) | (3 << COM0B0);
// Set our PWM duty cycle
OCR0B = -speed;
}
}
void pwm0_a_brake(void)
{
// Set motor speed to zero (turns off PWM):
pwm0_a(0);
// Enable both PD6 and PB2 to hit the brakes (POWER HUNGRY):
PORTD &= ~(1 << PD6);
PORTB &= ~(1 << PB2);
}
void pwm0_b_brake(void)
{
// Set motor speed to zero (turns off PWM):
pwm0_b(0);
// Enable both PD5 and PB1 to hit the brakes (POWER HUNGRY):
PORTD &= ~(1 << PD5);
PORTB &= ~(1 << PB1);
}
// That's really it for the motor stuff. The only other subroutine
// is a delay routine that will let us pause for a couple of seconds.
// Almost all the example code will have this routine in it.
// Delay for N seconds
void delay_sec(unsigned char sec)
{
unsigned int cycles;
// Delay 25ms at a time (38.4ms is the most we can delay with a
// 20MHz processor, unfortunately. See the delay.h include file
// for more info.)
for(cycles = 0; cycles < (sec * 40); cycles ++)
{
_delay_ms(25);
}
}
// And now for our main routine:
int main(void)
{
// Make sure all our registers are clear
DDRB = 0;
DDRC = 0;
DDRD = 0;
// Make sure all our pull-up resistors are clear
PORTB = 0;
PORTC = 0;
PORTD = 0;
// Initialize the timer0 PWM system:
pwm0_init();
// Motors are stopped when we initialize them, so there's
// no need to do that after the init routine.
// The endless loop
for(;;)
{
pwm0_a(150);
pwm0_b(150);
delay_sec(4);
pwm0_a(150);
pwm0_b(-150);
delay_sec(2);
}
// We never get here, but return a zero if we ever do.
return(0);
}
הרובוט לא עושה מה שהקוד אומר לו לעשות, בערך בשני הסיבובים הראשונים של הלולאה, הכל סבבה, אחר כך, נראה כאילו אין שום חוקיות בהתנהגות שלו ואין שום קשר לקוד. לרובוט לא מחוברים חיישנים בכלל (כרגע). לפני שעבדתי עם הרובוט הזה, חיברתי את הלוח לרובוט עם מנועים גדולים שחיממו את גשר ה-H האם יכול להיות שהגשר נשרף ולכן קשה לו לשלוט במנועים? או שאולי אתם רואים משהו בקוד שאני פיספסתי? או שהתקלה הזו יכולה להיגרם ממשהו אחר לגמרי...
אשמח לשמוע את דעתכם.
ארבל



