]> defiant.homedns.org Git - ros_wild_thumper.git/blobdiff - avr/motor_ctrl/main.c
avr motor_ctrl: watchdog configuration
[ros_wild_thumper.git] / avr / motor_ctrl / main.c
index 3642d4a8b222e59530eaafb28cb8a287f3dcd4da..a4c984dfa4e7e2cbd0219bc29bc7e2017b045b58 100644 (file)
@@ -8,6 +8,7 @@
 #include <util/twi.h>
 #include <avr/eeprom.h>
 #include <avr/wdt.h>
+#include <avr/pgmspace.h>
 #include "uart.h"
 
 /*
@@ -95,6 +96,8 @@
  * 0xA0 Reset reason
  * 0xA1 Error status
  * 0xA2 count test
+ * 0xA3 last i2c status before boot
+ * 0xA4 Watchdog enable
  * free
  * 0xff Bootloader
  */
 #define WHEEL_DIST 0.39912 // Measured: 0.252
 #define PWM_BREAK INT16_MIN
 #define STALL_LIMIT 140000
+#define I2C_TIMEOUT_DISABLE 255
 
 #define TWI_ACK   TWCR = (1<<TWINT) | (1<<TWEA) | (1<<TWEN) | (1<<TWIE)
 #define TWI_NAK   TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWIE)
@@ -183,6 +187,10 @@ static volatile uint8_t count_test=0;
 static volatile uint8_t front_handicap=0;
 static volatile uint8_t aft_handicap=0;
 static volatile uint8_t error_state=0;
+static volatile uint8_t last_man_update_count=0;
+static volatile uint8_t last_i2c_status = 0;
+static uint8_t last_i2c_status_boot = 0;
+static volatile uint8_t watchdog_enable = 0;
 
 ISR(TWI_vect)
 {
@@ -191,6 +199,7 @@ ISR(TWI_vect)
        static ufloat_t tmp_speed;
        static ufloat_t tmp_angle;
 
+       last_i2c_status = TW_STATUS;
        switch(TW_STATUS)
        {
                case TW_SR_SLA_ACK: // start write
@@ -349,6 +358,7 @@ ISR(TWI_vect)
                                        tmp_angle.i = tmp_angle.i << 8 | TWDR;
                                        cmd_vel.angle = tmp_angle.f;
                                        cmd_vel.bUpdate = 1;
+                                       last_man_update_count = 0;
                                        TWI_ACK;
                                        break;
                                case 0x90: // Motor 1 switch
@@ -377,12 +387,16 @@ ISR(TWI_vect)
                                        cmd_vel.bUpdate = 1;
                                        TWI_ACK;
                                        break;
+                               case 0xA4: // Watchdog enable
+                                       watchdog_enable = TWDR;
+                                       TWI_ACK;
+                                       break;
                                case 0xff: // bootloader
                                        bootloader = TWDR;
                                default:
                                        TWI_NAK;
                        }
-                       ireg++;
+                       if (ireg < 0xff) ireg++;
                        break;
                case TW_ST_SLA_ACK: // start read
                case TW_ST_DATA_ACK: // read
@@ -613,6 +627,12 @@ ISR(TWI_vect)
                                case 0xA2: // count test
                                        TWDR = count_test;
                                        TWI_ACK;
+                               case 0xA3: // last i2c status before boot
+                                       TWDR = last_i2c_status_boot;
+                                       TWI_ACK;
+                               case 0xA4: // Watchdog enable
+                                       TWDR = watchdog_enable;
+                                       TWI_ACK;
                                default:
                                        TWDR = 0;
                                        TWI_NAK;
@@ -622,9 +642,15 @@ ISR(TWI_vect)
                case TW_SR_STOP:
                        TWI_ACK;
                        break;
+               case TW_NO_INFO:
+                       break;
                default:
                        TWI_RESET;
        }
+
+       if (watchdog_enable == 2) {
+               wdt_reset();
+       }
 }
 
 
@@ -937,7 +963,8 @@ static void update_pid(void) {
                        speed1_wish_old = speed1_wish;
                }
 
-               if (speed1_wish == 0) {
+               uint8_t dir_change = (speed1_wish > 0 && speed1 < 0) || (speed1_wish < 0 && speed1 > 0); // Prevent dangerous immediate engine reverse
+               if (speed1_wish == 0 || dir_change) {
                        motor1 = 0;
                        eold1 = 0;
                        error_state &= ~(1<<4);
@@ -959,7 +986,8 @@ static void update_pid(void) {
                        speed2_wish_old = speed2_wish;
                }
 
-               if (speed2_wish == 0) {
+               uint8_t dir_change = (speed2_wish > 0 && speed2 < 0) || (speed2_wish < 0 && speed2 > 0); // Prevent dangerous immediate engine reverse
+               if (speed2_wish == 0 || dir_change) {
                        motor2 = 0;
                        eold2 = 0;
                        error_state &= ~(1<<5);
@@ -981,7 +1009,8 @@ static void update_pid(void) {
                        speed3_wish_old = speed3_wish;
                }
 
-               if (speed3_wish == 0) {
+               uint8_t dir_change = (speed3_wish > 0 && speed3 < 0) || (speed3_wish < 0 && speed3 > 0); // Prevent dangerous immediate engine reverse
+               if (speed3_wish == 0 || dir_change) {
                        motor3 = 0;
                        eold3 = 0;
                        error_state &= ~(1<<6);
@@ -1003,7 +1032,8 @@ static void update_pid(void) {
                        speed4_wish_old = speed4_wish;
                }
 
-               if (speed4_wish == 0) {
+               uint8_t dir_change = (speed4_wish > 0 && speed4 < 0) || (speed4_wish < 0 && speed4 > 0); // Prevent dangerous immediate engine reverse
+               if (speed4_wish == 0 || dir_change) {
                        motor4 = 0;
                        eold4 = 0;
                        error_state &= ~(1<<7);
@@ -1076,7 +1106,9 @@ int main(void) {
        TCCR0 = (1 << WGM01) | (1 << WGM00) | (1 << CS00);
        OCR0 = 0;
 
-       printf("\r\nStart\r\n");
+       printf_P(PSTR("\r\nStart\r\n"));
+
+       last_i2c_status_boot = eeprom_read_byte((uint8_t*)1);
 
        set_sleep_mode(SLEEP_MODE_IDLE);
        // Enable Timer 1 Overflow Interrupt
@@ -1085,6 +1117,15 @@ int main(void) {
 
        while(1) {
                switch(ireg) {
+                       case 0xA4: // Watchdog enable
+                               if (watchdog_enable == 1) {
+                                       wdt_enable(WDTO_2S);
+                                       watchdog_enable = 2;
+                               } else if (watchdog_enable == 0) {
+                                       wdt_disable();
+                                       watchdog_enable = 3;
+                               }
+                               break;
                        case 0xff: // Magic reg that starts the bootloader
                                if (bootloader == 0xa5) {
                                        cli();
@@ -1140,6 +1181,20 @@ int main(void) {
                        update_pid();
                        update_motor();
                        count_test++;
+                       if (last_man_update_count != I2C_TIMEOUT_DISABLE) last_man_update_count++;
+
+                       if (last_man_update_count >= 100) {
+                               // ~1s without a new i2c command
+                               cmd_vel.speed = 0;
+                               cmd_vel.angle = 0;
+                               cmd_vel.bUpdate = 1;
+                               if (last_man_update_count == 100) {
+                                       printf_P(PSTR("I2C State: 0x%x\r\n"), last_i2c_status);
+                                       eeprom_write_byte((uint8_t*)1, last_i2c_status);
+                                       eeprom_busy_wait();
+                               }
+                               last_man_update_count = I2C_TIMEOUT_DISABLE;
+                       }
                }
 
                sleep_mode();