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