Started following some tutorial on att85 usi. Downloaded example code from make avr book.
This commit is contained in:
@@ -0,0 +1,196 @@
|
||||
|
||||
##########------------------------------------------------------##########
|
||||
########## Project-specific Details ##########
|
||||
########## Check these every time you start a new project ##########
|
||||
##########------------------------------------------------------##########
|
||||
|
||||
MCU = atmega168p
|
||||
F_CPU = 8000000UL
|
||||
BAUD = 9600UL
|
||||
## Also try BAUD = 19200 or 38400 if you're feeling lucky.
|
||||
|
||||
## A directory for common include files and the simple USART library.
|
||||
## If you move either the current folder or the Library folder, you'll
|
||||
## need to change this path to match.
|
||||
LIBDIR = ../../AVR-Programming-Library
|
||||
|
||||
##########------------------------------------------------------##########
|
||||
########## Programmer Defaults ##########
|
||||
########## Set up once, then forget about it ##########
|
||||
########## (Can override. See bottom of file.) ##########
|
||||
##########------------------------------------------------------##########
|
||||
|
||||
PROGRAMMER_TYPE = usbtiny
|
||||
# extra arguments to avrdude: baud rate, chip type, -F flag, etc.
|
||||
PROGRAMMER_ARGS =
|
||||
|
||||
##########------------------------------------------------------##########
|
||||
########## Program Locations ##########
|
||||
########## Won't need to change if they're in your PATH ##########
|
||||
##########------------------------------------------------------##########
|
||||
|
||||
CC = avr-gcc
|
||||
OBJCOPY = avr-objcopy
|
||||
OBJDUMP = avr-objdump
|
||||
AVRSIZE = avr-size
|
||||
AVRDUDE = avrdude
|
||||
|
||||
##########------------------------------------------------------##########
|
||||
########## Makefile Magic! ##########
|
||||
########## Summary: ##########
|
||||
########## We want a .hex file ##########
|
||||
########## Compile source files into .elf ##########
|
||||
########## Convert .elf file into .hex ##########
|
||||
########## You shouldn't need to edit below. ##########
|
||||
##########------------------------------------------------------##########
|
||||
|
||||
## The name of your project (without the .c)
|
||||
# TARGET = blinkLED
|
||||
## Or name it automatically after the enclosing directory
|
||||
TARGET = $(lastword $(subst /, ,$(CURDIR)))
|
||||
|
||||
# Object files: will find all .c/.h files in current directory
|
||||
# and in LIBDIR. If you have any other (sub-)directories with code,
|
||||
# you can add them in to SOURCES below in the wildcard statement.
|
||||
SOURCES=$(wildcard *.c $(LIBDIR)/*.c)
|
||||
OBJECTS=$(SOURCES:.c=.o)
|
||||
HEADERS=$(SOURCES:.c=.h)
|
||||
|
||||
## Compilation options, type man avr-gcc if you're curious.
|
||||
CPPFLAGS = -DF_CPU=$(F_CPU) -DBAUD=$(BAUD) -I. -I$(LIBDIR)
|
||||
CFLAGS = -Os -g -std=gnu99 -Wall
|
||||
## Use short (8-bit) data types
|
||||
CFLAGS += -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums
|
||||
## Splits up object files per function
|
||||
CFLAGS += -ffunction-sections -fdata-sections
|
||||
LDFLAGS = -Wl,-Map,$(TARGET).map
|
||||
## Optional, but often ends up with smaller code
|
||||
LDFLAGS += -Wl,--gc-sections
|
||||
## Relax shrinks code even more, but makes disassembly messy
|
||||
## LDFLAGS += -Wl,--relax
|
||||
## LDFLAGS += -Wl,-u,vfprintf -lprintf_flt -lm ## for floating-point printf
|
||||
## LDFLAGS += -Wl,-u,vfprintf -lprintf_min ## for smaller printf
|
||||
TARGET_ARCH = -mmcu=$(MCU)
|
||||
|
||||
## Explicit pattern rules:
|
||||
## To make .o files from .c files
|
||||
%.o: %.c $(HEADERS) Makefile
|
||||
$(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c -o $@ $<;
|
||||
|
||||
$(TARGET).elf: $(OBJECTS)
|
||||
$(CC) $(LDFLAGS) $(TARGET_ARCH) $^ $(LDLIBS) -o $@
|
||||
|
||||
%.hex: %.elf
|
||||
$(OBJCOPY) -j .text -j .data -O ihex $< $@
|
||||
|
||||
%.eeprom: %.elf
|
||||
$(OBJCOPY) -j .eeprom --change-section-lma .eeprom=0 -O ihex $< $@
|
||||
|
||||
%.lst: %.elf
|
||||
$(OBJDUMP) -S $< > $@
|
||||
|
||||
## These targets don't have files named after them
|
||||
.PHONY: all disassemble disasm eeprom size clean squeaky_clean flash fuses
|
||||
|
||||
all: $(TARGET).hex
|
||||
|
||||
debug:
|
||||
@echo
|
||||
@echo "Source files:" $(SOURCES)
|
||||
@echo "MCU, F_CPU, BAUD:" $(MCU), $(F_CPU), $(BAUD)
|
||||
@echo
|
||||
|
||||
# Optionally create listing file from .elf
|
||||
# This creates approximate assembly-language equivalent of your code.
|
||||
# Useful for debugging time-sensitive bits,
|
||||
# or making sure the compiler does what you want.
|
||||
disassemble: $(TARGET).lst
|
||||
|
||||
disasm: disassemble
|
||||
|
||||
# Optionally show how big the resulting program is
|
||||
size: $(TARGET).elf
|
||||
$(AVRSIZE) -C --mcu=$(MCU) $(TARGET).elf
|
||||
|
||||
clean:
|
||||
rm -f $(TARGET).elf $(TARGET).hex $(TARGET).obj \
|
||||
$(TARGET).o $(TARGET).d $(TARGET).eep $(TARGET).lst \
|
||||
$(TARGET).lss $(TARGET).sym $(TARGET).map $(TARGET)~ \
|
||||
$(TARGET).eeprom
|
||||
|
||||
squeaky_clean:
|
||||
rm -f *.elf *.hex *.obj *.o *.d *.eep *.lst *.lss *.sym *.map *~ *.eeprom
|
||||
|
||||
##########------------------------------------------------------##########
|
||||
########## Programmer-specific details ##########
|
||||
########## Flashing code to AVR using avrdude ##########
|
||||
##########------------------------------------------------------##########
|
||||
|
||||
flash: $(TARGET).hex
|
||||
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) $(PROGRAMMER_ARGS) -U flash:w:$<
|
||||
|
||||
## An alias
|
||||
program: flash
|
||||
|
||||
flash_eeprom: $(TARGET).eeprom
|
||||
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) $(PROGRAMMER_ARGS) -U eeprom:w:$<
|
||||
|
||||
avrdude_terminal:
|
||||
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) $(PROGRAMMER_ARGS) -nt
|
||||
|
||||
## If you've got multiple programmers that you use,
|
||||
## you can define them here so that it's easy to switch.
|
||||
## To invoke, use something like `make flash_arduinoISP`
|
||||
flash_usbtiny: PROGRAMMER_TYPE = usbtiny
|
||||
flash_usbtiny: PROGRAMMER_ARGS = # USBTiny works with no further arguments
|
||||
flash_usbtiny: flash
|
||||
|
||||
flash_usbasp: PROGRAMMER_TYPE = usbasp
|
||||
flash_usbasp: PROGRAMMER_ARGS = # USBasp works with no further arguments
|
||||
flash_usbasp: flash
|
||||
|
||||
flash_arduinoISP: PROGRAMMER_TYPE = avrisp
|
||||
flash_arduinoISP: PROGRAMMER_ARGS = -b 19200 -P /dev/ttyACM0
|
||||
## (for windows) flash_arduinoISP: PROGRAMMER_ARGS = -b 19200 -P com5
|
||||
flash_arduinoISP: flash
|
||||
|
||||
flash_109: PROGRAMMER_TYPE = avr109
|
||||
flash_109: PROGRAMMER_ARGS = -b 9600 -P /dev/ttyUSB0
|
||||
flash_109: flash
|
||||
|
||||
##########------------------------------------------------------##########
|
||||
########## Fuse settings and suitable defaults ##########
|
||||
##########------------------------------------------------------##########
|
||||
|
||||
## Mega 48, 88, 168, 328 default values
|
||||
LFUSE = 0x62
|
||||
HFUSE = 0xdf
|
||||
EFUSE = 0x00
|
||||
|
||||
## Generic
|
||||
FUSE_STRING = -U lfuse:w:$(LFUSE):m -U hfuse:w:$(HFUSE):m -U efuse:w:$(EFUSE):m
|
||||
|
||||
fuses:
|
||||
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) \
|
||||
$(PROGRAMMER_ARGS) $(FUSE_STRING)
|
||||
show_fuses:
|
||||
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) $(PROGRAMMER_ARGS) -nv
|
||||
|
||||
## Called with no extra definitions, sets to defaults
|
||||
set_default_fuses: FUSE_STRING = -U lfuse:w:$(LFUSE):m -U hfuse:w:$(HFUSE):m -U efuse:w:$(EFUSE):m
|
||||
set_default_fuses: fuses
|
||||
|
||||
## Set the fuse byte for full-speed mode
|
||||
## Note: can also be set in firmware for modern chips
|
||||
set_fast_fuse: LFUSE = 0xE2
|
||||
set_fast_fuse: FUSE_STRING = -U lfuse:w:$(LFUSE):m
|
||||
set_fast_fuse: fuses
|
||||
|
||||
## Set the EESAVE fuse byte to preserve EEPROM across flashes
|
||||
set_eeprom_save_fuse: HFUSE = 0xD7
|
||||
set_eeprom_save_fuse: FUSE_STRING = -U hfuse:w:$(HFUSE):m
|
||||
set_eeprom_save_fuse: fuses
|
||||
|
||||
## Clear the EESAVE fuse byte
|
||||
clear_eeprom_save_fuse: FUSE_STRING = -U hfuse:w:$(HFUSE):m
|
||||
clear_eeprom_save_fuse: fuses
|
||||
@@ -0,0 +1,45 @@
|
||||
#include "_servoClockFunctions.h"
|
||||
|
||||
// Realtime-clock handling functions
|
||||
void initTimer0_Clock(void) {
|
||||
/* Normal mode, just used for the overflow interrupt */
|
||||
TCCR0B |= (1 << CS00); /* 8 MHz clock = ~31250 overflows per second */
|
||||
TIMSK0 |= (1 << TOIE0); /* timer overflow interrupt enable */
|
||||
}
|
||||
|
||||
void everySecond(void) {
|
||||
seconds++;
|
||||
if (seconds > 59) {
|
||||
seconds = 0;
|
||||
everyMinute();
|
||||
}
|
||||
LED_PORT ^= (1 << LED0); /* blink */
|
||||
printTime(hours, minutes, seconds); /* serial output */
|
||||
/* Turn off servo motor after three seconds into new minute */
|
||||
if (seconds == 3) {
|
||||
disableServo();
|
||||
}
|
||||
}
|
||||
void everyMinute(void) {
|
||||
minutes++;
|
||||
if (minutes > 59) {
|
||||
minutes = 0;
|
||||
everyHour();
|
||||
}
|
||||
// If during business hours, set servo to new minute
|
||||
// Otherwise, don't need to move motor when laser is off
|
||||
if ((hours >= START_TIME) && (hours < STOP_TIME)) {
|
||||
setServoPosition();
|
||||
enableServo();
|
||||
LASER_PORT |= (1 << LASER); /* make sure laser is on */
|
||||
}
|
||||
else { /* make sure laser is off */
|
||||
LASER_PORT &= ~(1 << LASER);
|
||||
}
|
||||
}
|
||||
void everyHour(void) {
|
||||
hours++;
|
||||
if (hours > 23) { /* loop around at end of day */
|
||||
hours = 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
|
||||
|
||||
#include "servoSundial.h"
|
||||
// Note: Global variables (ticks, seconds, minutes, hours)
|
||||
// are declared in servoSundial.h
|
||||
// and defined in servoSundial.c
|
||||
|
||||
// Realtime-clock handling functions
|
||||
|
||||
// This sets up the interrupt clock
|
||||
void initTimer0_Clock(void);
|
||||
|
||||
// These functions are called periodically
|
||||
// to update the global time variables
|
||||
// They cascade when needed (second -> minute)
|
||||
void everySecond(void);
|
||||
void everyMinute(void);
|
||||
void everyHour(void);
|
||||
@@ -0,0 +1,34 @@
|
||||
/* Functions for serial port output formatting and input */
|
||||
#include "_servoSerialHelpers.h"
|
||||
|
||||
void printTime(uint8_t hours, uint8_t minutes, uint8_t seconds) {
|
||||
printByte(hours);
|
||||
transmitByte(':');
|
||||
printByte(minutes);
|
||||
transmitByte(':');
|
||||
printByte(seconds);
|
||||
transmitByte('\r');
|
||||
transmitByte('\n');
|
||||
}
|
||||
|
||||
void pollSerial(void) {
|
||||
/* Poll for serial input -- to set the time. */
|
||||
char input;
|
||||
if (bit_is_set(UCSR0A, RXC0)) {
|
||||
input = UDR0;
|
||||
if (input == 'S') { /* enter set-time mode */
|
||||
printString("Setting time...\r\n");
|
||||
printString("Hour: ");
|
||||
hours = getNumber();
|
||||
printString("\r\nMinutes: ");
|
||||
minutes = getNumber();
|
||||
printString("\r\nSeconds: ");
|
||||
seconds = getNumber();
|
||||
printString("\r\n");
|
||||
ticks = 0;
|
||||
if ((hours >= START_TIME) && (hours < STOP_TIME)) {
|
||||
setServoPosition();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
/* Functions for serial port output formatting and input */
|
||||
|
||||
#include "servoSundial.h"
|
||||
// Prints out the time, nicely formatted
|
||||
void printTime(uint8_t hours, uint8_t minutes, uint8_t seconds);
|
||||
// Polls for serial input
|
||||
// sets the time if receives an "S"
|
||||
void pollSerial(void);
|
||||
@@ -0,0 +1,86 @@
|
||||
|
||||
|
||||
import time
|
||||
import serial
|
||||
|
||||
def readTime(serialPort):
|
||||
'''Reads the time from the AVR over the serial port'''
|
||||
serialPort.flushInput()
|
||||
character = ""
|
||||
while(not character == "\n"): # loop until see end of line
|
||||
character = serialPort.read(1)
|
||||
## The time string looks something like '011:045:023\r\n'
|
||||
timeString = serialPort.read(13)
|
||||
hms = timeString.split(":")
|
||||
hms = [int(x) for x in hms] # make hour, minute, second numeric
|
||||
return(hms)
|
||||
|
||||
def setTime(serialPort, hours, minutes, seconds):
|
||||
'''Sends the time over the serial port'''
|
||||
serialPort.flushOutput()
|
||||
serialPort.write("S")
|
||||
time.sleep(0.1) # delay while AVR sends
|
||||
serialPort.write(str(hours) + "\r")
|
||||
time.sleep(0.2) # delay while AVR sends
|
||||
serialPort.write(str(minutes) + "\r")
|
||||
time.sleep(0.2) # delay while AVR sends
|
||||
serialPort.write(str(seconds) + "\r")
|
||||
|
||||
def setTimeNow(serialPort):
|
||||
'''Sets the AVR clock to the current time'''
|
||||
hours, minutes, seconds = time.localtime()[3:6]
|
||||
setTime(serialPort, hours, minutes, seconds)
|
||||
return(time.time())
|
||||
|
||||
def calculateTimeDelay(serialPort):
|
||||
'''Gets AVR time and subtracts off actual (computer) time'''
|
||||
avrHMS = readTime(serialPort)
|
||||
hms = time.localtime()[3:6]
|
||||
hmsDifference = [x - y for x,y in zip(avrHMS, hms)]
|
||||
out = "AVR is fast by: {x[0]} hours, {x[1]} minutes, and {x[2]} seconds"
|
||||
print out.format(x=hmsDifference)
|
||||
return(hmsDifference)
|
||||
|
||||
def calculateTimeDrift(serialPort, startTime):
|
||||
'''Calculates the ratio to multiply OVERFLOWS_PER_SECOND
|
||||
given a start time and current error'''
|
||||
h, m, s = calculateTimeDelay(serialPort)
|
||||
driftSeconds = 60*60*h + 60*m + s
|
||||
elapsed = time.time() - startTime
|
||||
print "After {:.0f} seconds, ".format(elapsed)
|
||||
return (driftSeconds / elapsed + 1)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
## Set time automatically, recording start time,
|
||||
## then periodically calculate multiplication factor
|
||||
OVERFLOWS_PER_SECOND = 31250 # set this to equal the value in your code
|
||||
|
||||
SLEEP_TIME = 10
|
||||
ratioLog = []
|
||||
|
||||
s = serial.Serial("/dev/ttyUSB0", 9600, timeout=5)
|
||||
print "Setting time to current time...."
|
||||
ratio = 0
|
||||
while not ratio == 1: # make sure starting time is right on
|
||||
startTime = setTimeNow(s)
|
||||
ratio = calculateTimeDrift(s, startTime)
|
||||
|
||||
## Note: you can either leave this running or
|
||||
## you can re-run calculateTimeDrift() at any time in the future,
|
||||
## as long as you don't overwrite the original startTime
|
||||
while(True):
|
||||
ratio = calculateTimeDrift(s, startTime)
|
||||
ratioLog.append([time.time()-startTime, ratio])
|
||||
newOverflow = int(OVERFLOWS_PER_SECOND * ratio)
|
||||
print "OVERFLOWS_PER_SECOND should be {}\n\n".format(newOverflow)
|
||||
time.sleep(SLEEP_TIME)
|
||||
|
||||
## As you leave this routine running, you should see it bounce
|
||||
## around a lot in the beginning and then settle down after
|
||||
## running a few hours. Ironically, it'll converge to a good
|
||||
## number faster if it's initially very out of sync. (If it
|
||||
## drifts faster, you can figure out the drift rate sooner.)
|
||||
## Leave it running for 24 hours and you'll get one-second-per-day
|
||||
## accuracy.
|
||||
@@ -0,0 +1,6 @@
|
||||
import serial
|
||||
import calibrateTime
|
||||
|
||||
s = serial.Serial("/dev/ttyUSB0", 9600, timeout=5)
|
||||
calibrateTime.setTimeNow(s)
|
||||
s.close()
|
||||
@@ -0,0 +1,81 @@
|
||||
/* Quasi-realtime-clock with servo sundial. */
|
||||
|
||||
// ------- Includes -------- //
|
||||
#include "servoSundial.h"
|
||||
#include "_servoSerialHelpers.h"
|
||||
#include "_servoClockFunctions.h"
|
||||
|
||||
// -------- Global Variables --------- //
|
||||
volatile uint16_t ticks;
|
||||
volatile uint8_t hours = 15; /* arbitrary default time */
|
||||
volatile uint8_t minutes = 42;
|
||||
volatile uint8_t seconds = 57;
|
||||
|
||||
ISR(TIMER0_OVF_vect) {
|
||||
/* This is going off very frequently, so we should make it speedy */
|
||||
ticks++;
|
||||
}
|
||||
|
||||
// -------- Functions --------- //
|
||||
// Servo setup and utility functions
|
||||
void initTimer1_Servo(void) {
|
||||
/* Set up Timer1 (16bit) to give a pulse every 20ms */
|
||||
TCCR1A |= (1 << WGM11); /* Using Fast PWM mode */
|
||||
TCCR1B |= (1 << WGM12); /* counter max in ICR1 */
|
||||
TCCR1B |= (1 << WGM13);
|
||||
TCCR1B |= (1 << CS11); /* /8 prescaling -- microsecond steps */
|
||||
TCCR1A |= (1 << COM1A1); /* set output on PB1 / OC1A for servo */
|
||||
ICR1 = 20000; /* TOP value = 20ms */
|
||||
}
|
||||
|
||||
void enableServo(void) {
|
||||
while (TCNT1 < PULSE_OVER) {;
|
||||
} /* delay until pulse part of cycle done */
|
||||
SERVO_DDR |= (1 << SERVO); /* enable servo pulses */
|
||||
}
|
||||
|
||||
void disableServo(void) {
|
||||
while (TCNT1 < PULSE_OVER) {;
|
||||
} /* delay until pulse part of cycle done */
|
||||
SERVO_DDR &= ~(1 << SERVO); /* disable servo pulses */
|
||||
}
|
||||
|
||||
void setServoPosition(void) {
|
||||
uint32_t elapsedMinutes;
|
||||
/* using 32 bits b/c elapsedMinutes * PULSE_RANGE will overflow 16 bits */
|
||||
|
||||
|
||||
|
||||
elapsedMinutes = (hours - START_TIME) * 60 + minutes;
|
||||
OCR1A = PULSE_MIN + elapsedMinutes * PULSE_RANGE / (HOURS_RANGE * 60);
|
||||
enableServo();
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
|
||||
// -------- Inits --------- //
|
||||
clock_prescale_set(clock_div_1); /* CPU clock 8 MHz */
|
||||
initUSART();
|
||||
printString("\r\nWelcome to the Servo Sundial.\r\n");
|
||||
printString("Type S to set time.\r\n");
|
||||
|
||||
initTimer0_Clock();
|
||||
initTimer1_Servo();
|
||||
sei(); /* set enable interrupt bit */
|
||||
LED_DDR |= (1 << LED0); /* blinky output */
|
||||
LASER_DDR |= (1 << LASER); /* enable laser output */
|
||||
|
||||
// ------ Event loop ------ //
|
||||
while (1) {
|
||||
|
||||
/* Poll clock routine */
|
||||
if (ticks == OVERFLOWS_PER_SECOND) {
|
||||
ticks = 0;
|
||||
everySecond();
|
||||
}
|
||||
|
||||
pollSerial();
|
||||
|
||||
} /* End event loop */
|
||||
return 0; /* This line is never reached */
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/* Quasi-realtime-clock with servo sundial. */
|
||||
|
||||
// ------- Includes -------- //
|
||||
#include <avr/io.h>
|
||||
#include <util/delay.h>
|
||||
#include <avr/interrupt.h>
|
||||
#include <avr/power.h>
|
||||
#include "pinDefines.h"
|
||||
#include "USART.h"
|
||||
|
||||
// Global variables that take care of clock
|
||||
extern volatile uint16_t ticks;
|
||||
extern volatile uint8_t hours; /* arbitrary default time */
|
||||
extern volatile uint8_t minutes;
|
||||
extern volatile uint8_t seconds;
|
||||
|
||||
// ------- Defines -------- //
|
||||
#define PULSE_MIN 1000 /* experiment with these values */
|
||||
#define PULSE_MAX 2000 /* to match your own servo */
|
||||
#define PULSE_RANGE (PULSE_MAX - PULSE_MIN)
|
||||
#define PULSE_OVER 3000 /* Must be larger than PULSE_MAX */
|
||||
|
||||
#define START_TIME 10 /* 10 am */
|
||||
#define STOP_TIME 22 /* 10 pm */
|
||||
#define HOURS_RANGE (STOP_TIME - START_TIME - 1)
|
||||
|
||||
#define LASER PB2
|
||||
#define LASER_PORT PORTB
|
||||
#define LASER_DDR DDRB
|
||||
|
||||
#define SERVO PB1
|
||||
#define SERVO_PORT PORTB
|
||||
#define SERVO_DDR DDRB
|
||||
|
||||
#define OVERFLOWS_PER_SECOND 31250 /* nominal, should calibrate */
|
||||
|
||||
|
||||
// Serial input and output functions
|
||||
void pollSerial(void);
|
||||
void printTime(uint8_t hours, uint8_t minutes, uint8_t seconds);
|
||||
|
||||
// Servo setup and utility functions
|
||||
void initTimer1_Servo(void);
|
||||
void enableServo(void);
|
||||
void disableServo(void);
|
||||
void setServoPosition(void);
|
||||
|
||||
// Realtime-clock handling functions
|
||||
// Use the globals ticks, hours, minutes, seconds
|
||||
void initTimer0_Clock(void);
|
||||
void everyHour(void);
|
||||
void everyMinute(void);
|
||||
void everySecond(void);
|
||||
@@ -0,0 +1,17 @@
|
||||
import serial
|
||||
import calibrateTime
|
||||
import time
|
||||
|
||||
s = serial.Serial("/dev/ttyUSB0", 9600, timeout=5)
|
||||
|
||||
for hour in range(11,25):
|
||||
print "Moving to {}.".format(hour)
|
||||
calibrateTime.setTime(s, hour-2, 59, 59)
|
||||
time.sleep(2)
|
||||
for i in range(0, 60, 5):
|
||||
calibrateTime.setTime(s, hour-1, i, 00)
|
||||
time.sleep(0.5)
|
||||
calibrateTime.setTime(s, hour, 0, 0)
|
||||
discardThisInput = raw_input("\tpress return to continue\n")
|
||||
|
||||
s.close()
|
||||
@@ -0,0 +1,196 @@
|
||||
|
||||
##########------------------------------------------------------##########
|
||||
########## Project-specific Details ##########
|
||||
########## Check these every time you start a new project ##########
|
||||
##########------------------------------------------------------##########
|
||||
|
||||
MCU = atmega168p
|
||||
F_CPU = 1000000UL
|
||||
BAUD = 9600UL
|
||||
## Also try BAUD = 19200 or 38400 if you're feeling lucky.
|
||||
|
||||
## A directory for common include files and the simple USART library.
|
||||
## If you move either the current folder or the Library folder, you'll
|
||||
## need to change this path to match.
|
||||
LIBDIR = ../../AVR-Programming-Library
|
||||
|
||||
##########------------------------------------------------------##########
|
||||
########## Programmer Defaults ##########
|
||||
########## Set up once, then forget about it ##########
|
||||
########## (Can override. See bottom of file.) ##########
|
||||
##########------------------------------------------------------##########
|
||||
|
||||
PROGRAMMER_TYPE = usbtiny
|
||||
# extra arguments to avrdude: baud rate, chip type, -F flag, etc.
|
||||
PROGRAMMER_ARGS =
|
||||
|
||||
##########------------------------------------------------------##########
|
||||
########## Program Locations ##########
|
||||
########## Won't need to change if they're in your PATH ##########
|
||||
##########------------------------------------------------------##########
|
||||
|
||||
CC = avr-gcc
|
||||
OBJCOPY = avr-objcopy
|
||||
OBJDUMP = avr-objdump
|
||||
AVRSIZE = avr-size
|
||||
AVRDUDE = avrdude
|
||||
|
||||
##########------------------------------------------------------##########
|
||||
########## Makefile Magic! ##########
|
||||
########## Summary: ##########
|
||||
########## We want a .hex file ##########
|
||||
########## Compile source files into .elf ##########
|
||||
########## Convert .elf file into .hex ##########
|
||||
########## You shouldn't need to edit below. ##########
|
||||
##########------------------------------------------------------##########
|
||||
|
||||
## The name of your project (without the .c)
|
||||
# TARGET = blinkLED
|
||||
## Or name it automatically after the enclosing directory
|
||||
TARGET = $(lastword $(subst /, ,$(CURDIR)))
|
||||
|
||||
# Object files: will find all .c/.h files in current directory
|
||||
# and in LIBDIR. If you have any other (sub-)directories with code,
|
||||
# you can add them in to SOURCES below in the wildcard statement.
|
||||
SOURCES=$(wildcard *.c $(LIBDIR)/*.c)
|
||||
OBJECTS=$(SOURCES:.c=.o)
|
||||
HEADERS=$(SOURCES:.c=.h)
|
||||
|
||||
## Compilation options, type man avr-gcc if you're curious.
|
||||
CPPFLAGS = -DF_CPU=$(F_CPU) -DBAUD=$(BAUD) -I. -I$(LIBDIR)
|
||||
CFLAGS = -Os -g -std=gnu99 -Wall
|
||||
## Use short (8-bit) data types
|
||||
CFLAGS += -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums
|
||||
## Splits up object files per function
|
||||
CFLAGS += -ffunction-sections -fdata-sections
|
||||
LDFLAGS = -Wl,-Map,$(TARGET).map
|
||||
## Optional, but often ends up with smaller code
|
||||
LDFLAGS += -Wl,--gc-sections
|
||||
## Relax shrinks code even more, but makes disassembly messy
|
||||
## LDFLAGS += -Wl,--relax
|
||||
## LDFLAGS += -Wl,-u,vfprintf -lprintf_flt -lm ## for floating-point printf
|
||||
## LDFLAGS += -Wl,-u,vfprintf -lprintf_min ## for smaller printf
|
||||
TARGET_ARCH = -mmcu=$(MCU)
|
||||
|
||||
## Explicit pattern rules:
|
||||
## To make .o files from .c files
|
||||
%.o: %.c $(HEADERS) Makefile
|
||||
$(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c -o $@ $<;
|
||||
|
||||
$(TARGET).elf: $(OBJECTS)
|
||||
$(CC) $(LDFLAGS) $(TARGET_ARCH) $^ $(LDLIBS) -o $@
|
||||
|
||||
%.hex: %.elf
|
||||
$(OBJCOPY) -j .text -j .data -O ihex $< $@
|
||||
|
||||
%.eeprom: %.elf
|
||||
$(OBJCOPY) -j .eeprom --change-section-lma .eeprom=0 -O ihex $< $@
|
||||
|
||||
%.lst: %.elf
|
||||
$(OBJDUMP) -S $< > $@
|
||||
|
||||
## These targets don't have files named after them
|
||||
.PHONY: all disassemble disasm eeprom size clean squeaky_clean flash fuses
|
||||
|
||||
all: $(TARGET).hex
|
||||
|
||||
debug:
|
||||
@echo
|
||||
@echo "Source files:" $(SOURCES)
|
||||
@echo "MCU, F_CPU, BAUD:" $(MCU), $(F_CPU), $(BAUD)
|
||||
@echo
|
||||
|
||||
# Optionally create listing file from .elf
|
||||
# This creates approximate assembly-language equivalent of your code.
|
||||
# Useful for debugging time-sensitive bits,
|
||||
# or making sure the compiler does what you want.
|
||||
disassemble: $(TARGET).lst
|
||||
|
||||
disasm: disassemble
|
||||
|
||||
# Optionally show how big the resulting program is
|
||||
size: $(TARGET).elf
|
||||
$(AVRSIZE) -C --mcu=$(MCU) $(TARGET).elf
|
||||
|
||||
clean:
|
||||
rm -f $(TARGET).elf $(TARGET).hex $(TARGET).obj \
|
||||
$(TARGET).o $(TARGET).d $(TARGET).eep $(TARGET).lst \
|
||||
$(TARGET).lss $(TARGET).sym $(TARGET).map $(TARGET)~ \
|
||||
$(TARGET).eeprom
|
||||
|
||||
squeaky_clean:
|
||||
rm -f *.elf *.hex *.obj *.o *.d *.eep *.lst *.lss *.sym *.map *~ *.eeprom
|
||||
|
||||
##########------------------------------------------------------##########
|
||||
########## Programmer-specific details ##########
|
||||
########## Flashing code to AVR using avrdude ##########
|
||||
##########------------------------------------------------------##########
|
||||
|
||||
flash: $(TARGET).hex
|
||||
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) $(PROGRAMMER_ARGS) -U flash:w:$<
|
||||
|
||||
## An alias
|
||||
program: flash
|
||||
|
||||
flash_eeprom: $(TARGET).eeprom
|
||||
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) $(PROGRAMMER_ARGS) -U eeprom:w:$<
|
||||
|
||||
avrdude_terminal:
|
||||
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) $(PROGRAMMER_ARGS) -nt
|
||||
|
||||
## If you've got multiple programmers that you use,
|
||||
## you can define them here so that it's easy to switch.
|
||||
## To invoke, use something like `make flash_arduinoISP`
|
||||
flash_usbtiny: PROGRAMMER_TYPE = usbtiny
|
||||
flash_usbtiny: PROGRAMMER_ARGS = # USBTiny works with no further arguments
|
||||
flash_usbtiny: flash
|
||||
|
||||
flash_usbasp: PROGRAMMER_TYPE = usbasp
|
||||
flash_usbasp: PROGRAMMER_ARGS = # USBasp works with no further arguments
|
||||
flash_usbasp: flash
|
||||
|
||||
flash_arduinoISP: PROGRAMMER_TYPE = avrisp
|
||||
flash_arduinoISP: PROGRAMMER_ARGS = -b 19200 -P /dev/ttyACM0
|
||||
## (for windows) flash_arduinoISP: PROGRAMMER_ARGS = -b 19200 -P com5
|
||||
flash_arduinoISP: flash
|
||||
|
||||
flash_109: PROGRAMMER_TYPE = avr109
|
||||
flash_109: PROGRAMMER_ARGS = -b 9600 -P /dev/ttyUSB0
|
||||
flash_109: flash
|
||||
|
||||
##########------------------------------------------------------##########
|
||||
########## Fuse settings and suitable defaults ##########
|
||||
##########------------------------------------------------------##########
|
||||
|
||||
## Mega 48, 88, 168, 328 default values
|
||||
LFUSE = 0x62
|
||||
HFUSE = 0xdf
|
||||
EFUSE = 0x00
|
||||
|
||||
## Generic
|
||||
FUSE_STRING = -U lfuse:w:$(LFUSE):m -U hfuse:w:$(HFUSE):m -U efuse:w:$(EFUSE):m
|
||||
|
||||
fuses:
|
||||
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) \
|
||||
$(PROGRAMMER_ARGS) $(FUSE_STRING)
|
||||
show_fuses:
|
||||
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) $(PROGRAMMER_ARGS) -nv
|
||||
|
||||
## Called with no extra definitions, sets to defaults
|
||||
set_default_fuses: FUSE_STRING = -U lfuse:w:$(LFUSE):m -U hfuse:w:$(HFUSE):m -U efuse:w:$(EFUSE):m
|
||||
set_default_fuses: fuses
|
||||
|
||||
## Set the fuse byte for full-speed mode
|
||||
## Note: can also be set in firmware for modern chips
|
||||
set_fast_fuse: LFUSE = 0xE2
|
||||
set_fast_fuse: FUSE_STRING = -U lfuse:w:$(LFUSE):m
|
||||
set_fast_fuse: fuses
|
||||
|
||||
## Set the EESAVE fuse byte to preserve EEPROM across flashes
|
||||
set_eeprom_save_fuse: HFUSE = 0xD7
|
||||
set_eeprom_save_fuse: FUSE_STRING = -U hfuse:w:$(HFUSE):m
|
||||
set_eeprom_save_fuse: fuses
|
||||
|
||||
## Clear the EESAVE fuse byte
|
||||
clear_eeprom_save_fuse: FUSE_STRING = -U hfuse:w:$(HFUSE):m
|
||||
clear_eeprom_save_fuse: fuses
|
||||
@@ -0,0 +1,94 @@
|
||||
/* Quick interactive demo running servo with Timer 1 */
|
||||
|
||||
// ------- Preamble -------- //
|
||||
#include <avr/io.h>
|
||||
#include <util/delay.h>
|
||||
#include <avr/interrupt.h>
|
||||
|
||||
#include "pinDefines.h"
|
||||
#include "USART.h"
|
||||
|
||||
#define PULSE_MIN 1000 /* experiment with these values */
|
||||
#define PULSE_MAX 2000 /* to match your own servo */
|
||||
#define PULSE_MID 1500
|
||||
|
||||
static inline uint16_t getNumber16(void);
|
||||
|
||||
static inline void initTimer1Servo(void) {
|
||||
/* Set up Timer1 (16bit) to give a pulse every 20ms */
|
||||
/* Use Fast PWM mode, counter max in ICR1 */
|
||||
TCCR1A |= (1 << WGM11);
|
||||
TCCR1B |= (1 << WGM12) | (1 << WGM13);
|
||||
TCCR1B |= (1 << CS10); /* /1 prescaling -- counting in microseconds */
|
||||
ICR1 = 20000; /* TOP value = 20ms */
|
||||
TCCR1A |= (1 << COM1A1); /* Direct output on PB1 / OC1A */
|
||||
DDRB |= (1 << PB1); /* set pin for output */
|
||||
}
|
||||
|
||||
static inline void showOff(void) {
|
||||
printString("Center\r\n");
|
||||
OCR1A = PULSE_MID;
|
||||
_delay_ms(1500);
|
||||
printString("Clockwise Max\r\n");
|
||||
OCR1A = PULSE_MIN;
|
||||
_delay_ms(1500);
|
||||
printString("Counterclockwise Max\r\n");
|
||||
OCR1A = PULSE_MAX;
|
||||
_delay_ms(1500);
|
||||
printString("Center\r\n");
|
||||
OCR1A = PULSE_MID;
|
||||
_delay_ms(1500);
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
|
||||
// -------- Inits --------- //
|
||||
uint16_t servoPulseLength;
|
||||
OCR1A = PULSE_MID; /* set it to middle position initially */
|
||||
initTimer1Servo();
|
||||
initUSART();
|
||||
printString("\r\nWelcome to the Servo Demo\r\n");
|
||||
showOff();
|
||||
|
||||
// ------ Event loop ------ //
|
||||
while (1) {
|
||||
|
||||
printString("\r\nEnter a four-digit pulse length:\r\n");
|
||||
servoPulseLength = getNumber16();
|
||||
|
||||
printString("On my way....\r\n");
|
||||
OCR1A = servoPulseLength;
|
||||
DDRB |= (1 << PB1); /* re-enable output pin */
|
||||
|
||||
_delay_ms(1000);
|
||||
printString("Releasing...\r\n");
|
||||
while (TCNT1 < 3000) {;
|
||||
} /* delay until pulse part of cycle done */
|
||||
DDRB &= ~(1 << PB1); /* disable output pin */
|
||||
|
||||
} /* End event loop */
|
||||
return 0; /* This line is never reached */
|
||||
}
|
||||
|
||||
static inline uint16_t getNumber16(void) {
|
||||
// Gets a PWM value from the serial port.
|
||||
// Reads in characters, turns them into a number
|
||||
char thousands = '0';
|
||||
char hundreds = '0';
|
||||
char tens = '0';
|
||||
char ones = '0';
|
||||
char thisChar = '0';
|
||||
|
||||
do {
|
||||
thousands = hundreds; /* shift numbers over */
|
||||
hundreds = tens;
|
||||
tens = ones;
|
||||
ones = thisChar;
|
||||
thisChar = receiveByte(); /* get a new character */
|
||||
transmitByte(thisChar); /* echo */
|
||||
} while (thisChar != '\r');
|
||||
|
||||
transmitByte('\n'); /* newline */
|
||||
return (1000 * (thousands - '0') + 100 * (hundreds - '0') +
|
||||
10 * (tens - '0') + ones - '0');
|
||||
}
|
||||
Reference in New Issue
Block a user