Mercurial > nbob
changeset 0:181360e5ae22 draft
Initial commit
| author | Radomir Dopieralski <sheep-devel@sheep.art.pl> |
|---|---|
| date | Fri, 30 Dec 2016 00:22:45 +0100 |
| parents | |
| children | d62a960ce615 |
| files | .hgignore main/Makefile main/main.c main/servo.c main/servo.h |
| diffstat | 5 files changed, 245 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/.hgignore Fri Dec 30 00:22:45 2016 +0100 @@ -0,0 +1,7 @@ +syntax: glob +*~ +.*.swp +*.DS_Store +*.o +*.hex +*.elf
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main/Makefile Fri Dec 30 00:22:45 2016 +0100 @@ -0,0 +1,60 @@ +DEVICE = attiny85 +CLOCK = 8000000 +PROGRAMMER = -c usbasp +OBJECTS = main.o servo.o + +# for ATTiny85 +# see http://www.engbedded.com/fusecalc/ +FUSES = -U lfuse:w:0xe2:m -U hfuse:w:0xdf:m -U efuse:w:0xff:m +#-U lfuse:w:0x62:m -U hfuse:w:0xdf:m -U efuse:w:0xff:m + + +# Tune the lines below only if you know what you are doing: +AVRDUDE = avrdude $(PROGRAMMER) -p $(DEVICE) +COMPILE = avr-gcc -Wall -std=gnu99 -Os -DF_CPU=$(CLOCK) -mmcu=$(DEVICE) + +# symbolic targets: +all: main.hex + +.c.o: + $(COMPILE) -c $< -o $@ + +.S.o: + $(COMPILE) -x assembler-with-cpp -c $< -o $@ + +.c.s: + $(COMPILE) -S $< -o $@ + +flash: all + $(AVRDUDE) -U flash:w:main.hex:i + +fuse: + $(AVRDUDE) $(FUSES) + +# Xcode uses the Makefile targets "", "clean" and "install" +install: flash fuse + +# if you use a bootloader, change the command below appropriately: +load: all + bootloadHID main.hex + +clean: + rm -f main.hex main.elf $(OBJECTS) + +# file targets: +main.elf: $(OBJECTS) + $(COMPILE) -o main.elf $(OBJECTS) + +main.hex: main.elf + rm -f main.hex + avr-objcopy -j .text -j .data -O ihex main.elf main.hex + avr-size --format=avr --mcu=$(DEVICE) main.elf +# If you have an EEPROM section, you must also create a hex file for the +# EEPROM and add it to the "flash" target. + +# Targets for code debugging and analysis: +disasm: main.elf + avr-objdump -d main.elf + +cpp: + $(COMPILE) -E main.c`gg
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main/main.c Fri Dec 30 00:22:45 2016 +0100 @@ -0,0 +1,46 @@ +#include "servo.h" +#include <util/delay.h> + +const int8_t servo_pins[MAX_SERVOS] = {0, 127, 4, 127, 1}; + + +void pose(uint16_t left, uint16_t right, uint16_t sway) { + static uint16_t current_left = 1500; + static uint16_t current_right = 1500; + static uint16_t current_sway = 1500; + + while (left != current_left || + right != current_right || + sway != current_sway) { + if (left > current_left) { + ++current_left; + } else if (left < current_left) { + --current_left; + } + if (right > current_right) { + ++current_right; + } else if (right < current_right) { + --current_right; + } + if (sway > current_sway) { + ++current_sway; + } else if (sway < current_sway) { + --current_sway; + } + set_servo(0, current_left); + set_servo(2, current_sway); + set_servo(4, current_right); + _delay_ms(1); + } +} + +int main() { + servo_setup(); + + while (1) { + pose(2000, 1900, 1600); + pose(1200, 1100, 2000); + pose(1200, 1100, 1600); + pose(2000, 1900, 1200); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main/servo.c Fri Dec 30 00:22:45 2016 +0100 @@ -0,0 +1,115 @@ +#include <avr/io.h> +#include <avr/interrupt.h> +#include <inttypes.h> + +#include "servo.h" + + +#ifdef USE_TIMER0 + #define TCNTn TCNT0 + #define OCRnx OCR0A + #define OCFnx OCF0A + #define OCIEnx OCIE0A +#endif + +#ifdef USE_TIMER1 + #define TCNTn TCNT1 + #define OCRnx OCR1A + #define OCFnx OCF1A + #define OCIEnx OCIE1A +#endif + +#define STATE_PIN_HIGH 0 +#define STATE_PIN_LOW 1 +#define STATE_512US 2 +#define STATE_2048US 3 + +#define ISR_TIME 4 + + +volatile uint8_t servo_pulse[MAX_SERVOS] = {}; + + +void set_servo(uint8_t servo, uint16_t ms) { + servo_pulse[servo] = ms / 8 - 64; +} + +void servo_setup() { +#ifdef USE_TIMER0 + TCCR0B = 0; // reset timer control + + //set counter0 prescaler to 64 + //our FCLK is 8mhz so this makes each timer tick be 8 microseconds long + TCCR0B &= ~(1<< CS02); //clear + TCCR0B |= (1<< CS01); //set + TCCR0B |= (1<< CS00); //set +#endif +#ifdef USE_TIMER1 + TCCR1 = 0; // reset timer control + + //set counter1 prescaler to 64 + //our F_CPU is 8mhz so this makes each timer tick be 8 microseconds long + TCCR1 &= ~(1<< CS13); //clear + TCCR1 |= (1<< CS12); //set + TCCR1 |= (1<< CS11); //set + TCCR1 |= (1<< CS10); //set +#endif + + TIMSK |= (1 << OCIEnx); + TCNTn = 0; + OCRnx = 255; + + for (uint8_t servo=0; servo < MAX_SERVOS; ++servo) { + servo_pulse[servo] = 128; + DDRB |= 1 << servo_pins[servo]; + } + sei(); +} + +#ifdef USE_TIMER0 +ISR(TIM0_COMPA_vect) +#endif +#ifdef USE_TIMER1 +ISR(TIM1_COMPA_vect) +#endif +{ + static uint8_t state = 0; + static uint8_t servo = 0; + + switch (state) { + case STATE_PIN_HIGH: // set pin high and wait 512us + ++servo; + if (servo >= MAX_SERVOS) { + servo = 0; + } + PORTB |= 1 << servo_pins[servo]; // set pin + OCRnx = 64 - ISR_TIME; // 512us + state = STATE_512US; + break; + case STATE_512US: // start counting pulse width + OCRnx = servo_pulse[servo]; + if (OCRnx == 0) { + TCNTn = 0xff; // overflow + } else { + TIFR = 1<<OCF0A; // clear the flag + } + state = STATE_PIN_LOW; + break; + case STATE_PIN_LOW: + PORTB &= ~(1 << servo_pins[servo]); // clear pin + uint8_t pulse = 64 + servo_pulse[servo]; + if (pulse > 255) { // longer than 2048us + OCRnx = 512 - pulse; + state = STATE_PIN_HIGH; + } else { + OCRnx = 255 - pulse; + state = STATE_2048US; + } + break; + case STATE_2048US: // continue pulse width + OCRnx = 255; + state = STATE_PIN_HIGH; + break; + }; + TCNTn = 0; // reset counter +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main/servo.h Fri Dec 30 00:22:45 2016 +0100 @@ -0,0 +1,17 @@ +#ifndef SERVO_H +#define SERVO_H + +#include <inttypes.h> + + +#define MAX_SERVOS 5 +#define USE_TIMER0 + + +extern volatile uint8_t servo_pulse[MAX_SERVOS]; +extern const int8_t servo_pins[MAX_SERVOS]; + +void set_servo(uint8_t servo, uint16_t ms); +void servo_setup(); + +#endif
