From c66c8a0defb787ba608ba5b42ca58b51a1169aca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucas=20Ple=C3=9F?= Date: Tue, 3 Jun 2014 16:29:55 +0200 Subject: [PATCH] changed the serial protocol and cleaned up the code, fixed a bug in the timer (PWM got inverted sometimes) --- .../displayboard_servo/software/src/main.c | 164 ++++++++---------- .../displayboard_servo/software/src/utils.c | 5 + schaltungen/displayboard_servo/tester.py | 42 ++--- 3 files changed, 97 insertions(+), 114 deletions(-) diff --git a/schaltungen/displayboard_servo/software/src/main.c b/schaltungen/displayboard_servo/software/src/main.c index e01b768..82cdea9 100644 --- a/schaltungen/displayboard_servo/software/src/main.c +++ b/schaltungen/displayboard_servo/software/src/main.c @@ -12,113 +12,77 @@ #define POWER_MAX 400 #define SERVO_STEPS 125 -#define BUFSIZE 32 +#define BUFSIZE 10 volatile uint16_t syscounter = 0; - -// values send over uart from powerboard -typedef struct { - uint16_t voltage_gen; - uint16_t voltage_reg; - uint16_t current_gen; - - struct { - uint8_t loadsw : 1; - uint8_t gensw : 1; - uint8_t batsw : 1; - }; -} PWR_DATA; - -static PWR_DATA pd; +volatile uint16_t power; uint8_t data_count = 0; char data_in[BUFSIZE]; + void reset_input_buffer(void) { data_count = 0; memset(data_in, 0, BUFSIZE); } - -static void update_servo_position() { - uint32_t power; - power = ( (pd.voltage_gen / 100) * (pd.current_gen / 100) ) / 100; - set_servo(power & 0xffff); -} static void timer_init(void) { // CTC Mode for Timer 1 (16Bit) with prescale of 64 TCCR1B |= _BV(WGM12) | _BV(CS11) | _BV(CS10); OCR1A = 2250; // set Servo to max. position TIMSK |= _BV(OCIE1A); // enable timer interrupt - TCCR1A |= (1<= BUFSIZE) { // buffer overflow reset_input_buffer(); } + +#ifdef DEBUG + for(uint8_t i=0;i 1) { // \n + + power = atol(data_in); + if(power > POWER_MAX) power = POWER_MAX; + +#ifdef DEBUG + uart_puts_P("power = "); + uart_print_uint16(power); + uart_puts_P("\r\n"); + +#endif + + set_servo(power); + + reset_input_buffer(); + } } } @@ -129,34 +93,40 @@ static void work_uart() { */ void set_servo(uint16_t display) { - if( display < 1 ) display = POWER_MIN; if( display > POWER_MAX ) display = POWER_MAX; - display = POWER_MAX-display; // invert the value / servo + display = POWER_MAX-display; // invert the value / servo display = display * 10; // *10 otherwise we need float - display = display / ( (POWER_MAX*10) / SERVO_STEPS ); + display = display / ((POWER_MAX * 10) / SERVO_STEPS); display = display + SERVO_STEPS; +#ifdef DEBUG uart_puts_P("display = "); uart_print_uint16(display); uart_puts_P("\r\n"); +#endif - //cli(); // read and write atomic - TIMSK &= ~_BV(OCIE1A); - - if( display < 125 ) display = 125; // just make sure, the timer + if( display < 125 ) display = 125; // just make sure, the timer if( display > 250 ) display = 250; // is never out ouf 20ms grid - OCR1A = 2500-display; - TIMSK |= _BV(OCIE1A); + + // check if timer is currently in the small pulse, then sleep here 2ms + // and do again + if(OCR1A < 2250) { + _delay_ms(2); + } + + cli(); // read and write atomic + OCR1A = 2500-display; + sei(); } /** * \brief the method moves the servo one complete cycle */ -void demo_display(void) { +static void demo_display(void) { set_servo(0); wait(100); set_servo(400); @@ -179,12 +149,17 @@ int main(void) { while(1) { work_uart(); - if((syscounter % 25) == 0) { // about every 500ms + if(syscounter >= 100) { reset_input_buffer(); uart_putc('a'); // send a to receive values from master box + syscounter = 0; + +#ifdef DEBUG + uart_puts_P("OCR1A = "); + uart_print_uint16(OCR1A); + uart_puts_P("\r\n"); +#endif } - - syscounter %= 1000; } return(0); @@ -195,10 +170,11 @@ int main(void) { * the system clock varies a bit, but this does not matter */ ISR(TIMER1_COMPA_vect) { - syscounter++; OCR1A = 2500-OCR1A; // Das Servosignal wird aus der Differenz von // Periodenlänge (2500*0,008ms=20ms) und letztem // Vergleichswert (OCR1A) gebildet } - +ISR(TIMER0_COMPA_vect) { + syscounter++; +} diff --git a/schaltungen/displayboard_servo/software/src/utils.c b/schaltungen/displayboard_servo/software/src/utils.c index 97db470..2cfd35d 100644 --- a/schaltungen/displayboard_servo/software/src/utils.c +++ b/schaltungen/displayboard_servo/software/src/utils.c @@ -47,5 +47,10 @@ void uart_print_uint16(uint16_t x) { uart_putc(48 + (x % 100 / 10 )); uart_putc(48 + (x % 10)); } +void uart_print_uint8(uint8_t x) { + uart_putc(48 + (x % 1000 / 100 )); + uart_putc(48 + (x % 100 / 10 )); + uart_putc(48 + (x % 10)); +} diff --git a/schaltungen/displayboard_servo/tester.py b/schaltungen/displayboard_servo/tester.py index 926b6c0..e877887 100755 --- a/schaltungen/displayboard_servo/tester.py +++ b/schaltungen/displayboard_servo/tester.py @@ -6,30 +6,32 @@ import time ser = serial.Serial("/dev/ttyUSB0", 38400) -voltage = 20000 -current = 0 +power = 0 incdec = 0 while 1: tdata = ser.read() time.sleep(1) - data_left = ser.inWaiting() - tdata += ser.read(data_left) - - out = "A%05d,12300,%05d,1,1,1B" % (voltage, current) - print out - ser.write(out) - if incdec == 0: - current = current + 1000 + if tdata == 'a': + print power + ser.write(str(power) + '\n') + #ser.write('100\n') + ser.flush() + + if incdec == 0: + power = power + 10 + else: + power = power - 10 + + if power > 400: + power = 400 + incdec = 1 + + if power < 0: + power = 0 + incdec = 0 else: - current = current - 1000 - - if current > 20000: - current = 20000 - incdec = 1 - - if current < 0: - current = 0 - incdec = 0 - + data_left = ser.inWaiting() + tdata += ser.read(data_left) + print tdata