OK, now that I've shrunk the code for #Nyan Board to 470 bytes, it's time to look at the code for the ears. This time I'm going to got straight into plain C. All I need to do is to figure out how to do analogRead()... Turns out it's super-simple!
#include <avr/io.h>
#include <util/delay.h>
#define MIN(X, Y) (((X) < (Y)) ? (X) : (Y))
int16_t adc(int8_t pin) {
ADMUX = 0<<ADLAR | 0<<REFS1 | 0<<REFS0 | pin & 0x03;
ADCSRA |= 1<<ADSC;
while (ADCSRA & 1<<ADSC) {
// Pass.
}
return ADC - 512;
}
void update_servos(uint8_t left_position, uint8_t right_position) {
static uint8_t current_left = 0;
static uint8_t current_right = 0;
uint8_t left = 17 + MIN(left_position, 15);
if (current_left < left) {
++current_left;
OCR0A = current_left;
} else if (current_left > left) {
--current_left;
OCR0A = current_left;
} else {
OCR0A = 255;
}
uint8_t right = 33 - MIN(right_position, 15);
if (current_right < right) {
++current_right;
OCR0B = current_right;
} else if (current_right > right) {
--current_right;
OCR0B = current_right;
} else {
OCR0B = 255;
}
}
int running_average(int16_t *buffer, uint8_t *cursor,
int16_t *total, int16_t value) {
*total -= buffer[*cursor];
buffer[*cursor] = value;
*total += value;
*cursor = (*cursor + 1) & 0x0F;
return *total >> 4;
}
int main () {
static uint8_t left = 7;
static uint8_t right = 7;
static int16_t x_buffer[16] = {};
static int16_t y_buffer[16] = {};
static int16_t z_buffer[16] = {};
static uint8_t x_cursor = 0;
static uint8_t y_cursor = 0;
static uint8_t z_cursor = 0;
static int16_t x_total = 0;
static int16_t y_total = 0;
static int16_t z_total = 0;
// Init ADC.
ADCSRA = 1<<ADEN | 1<<ADPS2 | 1<<ADPS1 | 1<<ADPS0; // Pre-scaler 128.
// Output pins PB0 and PB1.
DDRB = 1<<0 | 1<<1;
// Setup the PWM clock to ~62.5Hz for the servos.
TCCR0A = 2<<COM0A0 | 2<<COM0B0 | 3<<WGM00;
TCCR0B = 0<<WGM02 | 1<<CS00 | 1<<CS01 | 0<<CS02;
OCR0A = 0;
OCR0B = 0;
while (1) {
int16_t z = running_average(x_buffer, &x_cursor, &x_total, adc(1) - 16);
int16_t y = running_average(y_buffer, &y_cursor, &y_total, adc(2));
int16_t x = running_average(z_buffer, &z_cursor, &z_total, adc(3));
if (x > 20) {
left = 15;
right = 15;
} else if (x < -20) {
left = 0;
right = 0;
} else if (y > 20) {
left = 15;
right = 0;
} else if (y < -20) {
left = 0;
right = 15;
} else {
left = 7;
right = 7;
}
update_servos(left, right);
_delay_ms(60);
}
}
The new code is not as minimalistic as in the case of Nyan Board -- in particular, I'm using much more memory here, for all the running average buffers -- but it's nice and small.
AVR Memory Usage ---------------- Device: attiny85 Program: 484 bytes (5.9% Full) (.text + .data + .bootloader) Data: 109 bytes (21.3% Full) (.data + .bss + .noinit)
Discussions
Become a member
In order to follow projects & hackers or give likes
Already a member?you need to create an account.