out DDRB,r16 ; DDRB == data direction register B
out PortB,r16 ; send a 'high' to PB5 only
Start:
rjmp Start ; hang in an infinite loop
,,,
upload this hex file to the arduino with
avrdude -p m328p -c stk500v1 -b 57600 -P /dev/ttyUSB0 -U flash:w:hello.hex
This is not working. The problem is the 'stk500' which may be
correct for the 'uno' arduino but not for the duemilenovo.
see below for a working example. The
problem seems to be the -c stk500v1 option
also try for arduino uno s etc
-b 115200 and the port -P /dev/ttyACM0
Architecture ‹↑›
The atmel atmega chips are 8 bit risc processors. They have
a stack and a register file. Data memory and program memory
are separate (program memory is stored in flash).
Avr Assembly ‹↑›
a good avr assembly site
https://sites.google.com/site/avrasmintro/
http://maxembedded.com/2011/06/the-adc-of-the-avr/
A reasonable explanation of the functioning of the
adc for avr chips.
Adc is yet another acronym meaning analogue to digital
conversion and is included in almost all microcontrollers.
Most sensors work by varying resistance or voltage depending
on some environmental factor such as light, sound, temperature,
pressure etc. This varying resistance gets translated into a
varying voltage input into one of the avr chips input pins.
The varying voltage is refered to as an 'analogue signal' or
analogue input.
The ADC module of the microcontroller converts this into a
digital number within a certain range. So that the MC can
then analyse the value of the input.
This stands for pulse width modulation. There is a duty cycle.
This is a kind of approximated analogue output using
digital highs and lows.
pwm code for an atmega8 (not sure if applicable to m328)
#define fillrate OCR2A
// main()
PORTB=0x00;
DDRB=0x08; //We use PORTB.3 as output, for OC2A, see the atmega8 reference manual
// Mode: Phase correct PWM top=0xFF
// OC2A output: Non-Inverted PWM
TCCR2A=0x81;
// Set the speed here, it will depend on your clock rate.
TCCR2B=0x02;
// for example, this will alternate between 75% and 42% PWM
while(1)
{
fillrate = 191; // ca. 75% PWM
delay_ms(2000);
fillrate = 107; // ca. 42% PWM
delay_ms(2000);
}
Timers ‹↑›
http://electronics.stackexchange.com/questions/2057/polyphonic-sounds-from-a-microcontroller
some timer info
timer (or counter) in normal mode, counts 0 to 255 then sets overflow.
Prescaler, or divider, divides the system clock by value
set the prescaler
ldi r16, 0b00000011 ; set timer prescaler = 64
out TCCR0B, r16 ; timer control register B
Prescaler values are limited to the following. The higher the
prescaler value, then the slower the timer with count up to 256
1, TCCR0B = 0b0000001
8, TCCR0B = 0b0000010
64, TCCR0B = 0b0000011
256, TCCR0B = 0b0000100
1024, TCCR0B = 0b0000101
To calculate delay for timer/counter user
clock/prescaler * 256
eg 16 Mhz /1024 * 256 = ??
blinking a led using the timer (counter) with prescaler
; blinks an LED which is connected to PB5 (digital out 13)
.include "m328Pdef.inc"
rjmp start
sleep:
in r16, TIFR0 ; get timer flags register 0
andi r16, 0b00000010 ; tov0 ~ timer overflow flag (bit 2)
breq sleep ; if overflow not set, then loop
ldi r16, 0b00000010 ; reset timer overflow flag by setting it
out TIFR0, r16 ; to 1
ret
start:
ldi r19,0b00100000 ; or try etc "sbi ddrb, 0"
out DDRB,r19 ; ddrb ~ data direction register B
ldi r16, 0b00000101 ; set timer prescaler = 1024
out TCCR0B, r16 ; timer control register B
again:
ldi r19,0b00100000 ; or try sbi instruction for toggling
out PortB,r19 ;
rcall sleep
ldi r19,0b00000000 ; turn off led
out PortB,r19 ; send to pin on port b
rcall sleep
rjmp again
If we preload the counter with eg 128 then the timer overflows
twice as quickly
preload the timer counter
ldi r16, 128 ; preload timer with 128
out TCNT0, r16 ; timer count register := 128
blinking a led using the timer with prescaler and preloaded counter
; LED connected to PB5 (digital out 13)
.include "m328Pdef.inc"
rjmp start
sleep:
in r16, TIFR0 ; get timer flags register 0
andi r16, 0b00000010 ; tov0 ~ timer overflow flag (bit 2)
breq sleep ; if overflow not set, then loop
ldi r16, 0b00000010 ; reset timer overflow flag by setting it
out TIFR0, r16 ; to 1
ret
start:
ldi r19,0b00100000 ; or try etc "sbi ddrb, 0"
out DDRB,r19 ; ddrb ~ data direction register B
ldi r16, 0b00000101 ; set timer prescaler = 1024
out TCCR0B, r16 ; timer control register B
again:
ldi r16, 128 ; preload timer with 128
out TCNT0, r16
ldi r19,0b00100000 ; or try sbi instruction for toggling
out PortB,r19 ;
rcall sleep
ldi r19,0b00000000 ; turn off led
out PortB,r19 ; send to pin on port b
rcall sleep
rjmp again
By using interrupts the avr is free to do other things
use the timer using interrupts
---------
.include "m328Pdef.inc"
.def a = r16 ;general purpose accumulator
.org 0000
rjmp on_reset ;reset vector
.org 0003
rjmp tim0_ovf ; timer0 overflow handler
on_reset:
sbi ddrb, 0 ; set portb0 for output
ldi a, 0b00000101 ; set prescaler to /1024
out tccr0b, a ; timer/counter control register "b"
ldi a, 0b00000010 ; enable timer-overflow interupt
; No, timsk0 is not accessible with out
; out TIMSK0, a ; timer interrupt mask register
; sts = store direct to data space
sts timsk0, a ; timer interrupt mask register
sei ; enable interupts globally
; timer overflow interrupt handler
tim0_ovf:
sbi pinb,0 ; flip the 0 bit
reti
; main loop
start:
nop ;do nothing
rjmp start
,,,
Delays ‹↑›
simple blinking code using about a 1 second delay
; turns on an LED which is connected to PB5 (digital out 13)
.include "/usr/share/avra/m328Pdef.inc"
ldi r19,0b00100000 ; or try etc "sbi ddrb, 0"
out DDRB,r19 ; ddrb ~ data direction register B
again:
ldi r19,0b00100000 ;
out PortB,r19 ;
clr r16 ; set reg16 := 0
clr r17
ldi r18, 40
here: ; a delay loop 40*256^2 instructions
dec r16 ;
brne here
dec r17
brne here
dec r18
brne here
ldi r19,0b00000000
out PortB,r19
ldi r18, 40
far:
dec r16
brne far
dec r17
brne far
dec r18
brne far
rjmp again
Arduino ‹↑›
install the arduino java software
sudo apt-get install arduino
Then select the serial device and board (eg duemilenove)
Then select file/preferences and check box for verbose
info during upload
run arduino software with privelidges
sudo arduino
If you dont have the right priviledges the serial port
will be greyed out.
It doesnt seem to matter what usb socket the cable is
plugged into at all. (at least not on my linux mint machine)
the following worked for me
sudo avrdude -v -v -v -v -p atmega328p -carduino -P/dev/ttyUSB0 -b57600 -D -Uflash:w:hello.hex:i
the same without verbose output
sudo avrdude -p atmega328p -carduino -P/dev/ttyUSB0 -b57600 -D -Uflash:w:hello.hex:i
below is a typical avrdude command from the ide
/usr/share/arduino/hardware/tools/avrdude -C/usr/share/arduino/hardware/tools/avrdude.conf -v -v -v -v -patmega328p -carduino -P/dev/ttyUSB0 -b57600 -D -Uflash:w:/tmp/build5695632546898703228.tmp/sketch_mar13a.cpp.hex:i
avrdude options
-c the programmer |
-P the serial port |
code to make an avr microcontroller do nothing
here: rjmp here
http://avrprog.pbworks.com/w/page/9345379/AvrSound
a good simple program to play midi file squeakily on a
piezo buzzer
Piezo Buzzers ‹↑›
This is a small device for playing sound. Apparently it can
also operate as a sensor
The piezo buzzer can make tunes by simply toggling the output
on a pin at a certain frequency. But this job is perhaps better
done with pulse width modulation using a %50 duty-cycle
square wave, at different frequencies.
All this can be done much better with timers and interrupts.
we can also simplify by using the pinb trick to toggle
and output pin
circuit: pin13->100R(??)-->piezo-->Ground
buzz a piezo connected to arduino pin 13 then to ground
.include "/usr/share/avra/m328Pdef.inc"
ldi r19,0b00100000
out DDRB,r19
again:
ldi r19,0b00100000
out PortB,r19
clr r16
clr r17
ldi r18, 4
here:
dec r16
brne here
dec r17
brne here
dec r18
brne here
ldi r19,0b00000000
out PortB,r19
ldi r18, 4
far:
dec r16
brne far
dec r17
brne far
dec r18
brne far
rjmp again
The code is not working properly below
another pause routine adapted from 'retrodan' code
.include "/usr/share/avra/m328Pdef.inc"
.DEF A = R16 ;GENERAL PURPOSE ACCUMULATOR
.DEF I = R20 ;INDEX
.DEF N = R22 ;COUNTER
;.ORG 0000
ON_RESET:
ldi r19,0b00100000
out DDRB,r19
; SBI DDRB,5 ;SET PORTB0 FOR OUTPUT
main:
SBI PINB,5 ;TOGGLE THE BIT
;RCALL PAUSE ;WAIT/PAUSE
rjmp main ;go back and do it again
; pause routines
PAUSE: LDI N,0 ;DO NOTHING LOOP
PLUPE:
; RCALL np ; CALLS ANOTHER DO NOTHING LOOP
DEC N ; CHECK IF WE COME BACK TO ZERO
BRNE PLUPE ; IF NOT LOOP AGAIN
RET ;RETURN FROM CALL
np: LDI I,0 ;START AT ZERO
MPLUP: DEC I ;SUBTRACT ONE
BRNE MPLUP ;KEEP LOOPING UNTIL WE HIT ZERO
RET ;RETURN FROM CALL
Below is working but there is a mysterious error
with high(ramend) etc
another attempt
.include "/usr/share/avra/m328Pdef.inc"
; .INCLUDE "M169DEF.INC"
.DEF A = r16
.DEF I = r21
.org $0000
reset:
;ldi a, high(ramend)
;OUT SPH,A
;LDI A,LOW(RAMEND)
;OUT SPL,A
SBI DDRB,5
again: rcall bpause
sbi pinb,5 ; toggle arduino output 13 pin
rjmp again
bpause:
BLOOP: LDI I,5
BPLUPE: DEC I
BRNE BPLUPE
DEC A
BRNE BLOOP
RET
;SETUP THE STACK POINTER
;AT TOP OF MEMORY AND
;GROW DOWNWARDS
;CONFIG SPEAKER PORT
;WAIT
;CLICK THE SPEAKER
;DO IT AGAIN
;PAUSE ROUTINE
;TIME DEPENDS ON "A"
Batteries are rated by their mAh which means "milliamp hours"
so an AA battery rated at 1000mAh could in theory produce
1 milli-amp for 1000 hours. If a project is powered by battery
or solar panel, then its really a good idea to reduce power
consumption.
Arduino Uno draws 42mA (per hour)
https://www.openhomeautomation.net/arduino-battery/
an excelent tutorial for powering an atmega328 on a
breadboard with only 2 AA batteries and no voltage regulator.
The atmega is powered at 3V with an external crystal.
Also discusses ways to make the atmega328 use less power
http://arduino.cc/en/main/standalone
How to put the arduino on a bread-board powered with a ~9volt
battery and using a 7805 voltage regulator to reduce voltage
to 5V. Apparently this type of regulator wastes energy
http://arduino.cc/en/Tutorial/ArduinoToBreadboard
similar to above but without incircuit programming of the
atmega chip.
https://alanbmitchell.wordpress.com/2011/10/02/operate-arduino-for-year-from-batteries/
another low power article
Low Power ‹↑›
The atmega328 has 5 modes to reduce power consumption which
can be activated through code.
Ideas to reduce power consumption,
use the on-chip oscillator and clock at 8Megahz.
Use a 'switching' voltage regulator.
run chip at 3V or 3.3V
turn off unused stuff, like ADC etc
you can throttle the internal clock of the ATmega328 on the fly.
see CLKPR. You can educe the internal 8MHz clock to 31.250kHz
with two lines of code.
Sleep Modes ‹↑›
http://www.engblaze.com/hush-little-microprocessor-avr-and-arduino-sleep-mode-basics/
a tutorial about avr sleep modes.
Battery Power ‹↑›
CR2032 20mm coin cell battery
runs at 3V and doesnt require a voltage regulator. but only has
a rating of 200mAh so low power consumption is necessary.
LR123 type lithium cell.
high amp hours rating
Solar Power ‹↑›
Powering an arduino or atmega with solar seems feasible
put panels in series to increase voltage, and in parallel
to increase amperage.
http://www.instructables.com/id/Solar-powered-arduino-on-the-back-of-a-playing-car/
This is a very interesting blog on how to create a playing card
sized solar panel to power an arduino
avra is an assembler for use with avr chips. This is good if
you dont like c or java.
to use register names you need an 'inc' file for the chip
eg: /usr/share/avra/tn13def.inc
avra doesnt seem to come with an inc file for the
atmega328 but one should be findable
compile a file to a hex file
avra hello.asm
Vim And Avr Programming ‹↑›
Vim can be used to compile, and upload to the arduino board
code in a text file, or even code contained within another
type of text document.
map the key sequence ';av' to compile the whole file with avra
map ;as :!avra %<cr>
or >> map ;as :!avra % -o %:r.hex<cr>
The second example is not necessary since by default avra
creates a file called name.hex where the source file is 'name.asm'
In the examples below, the complete assembly program is
supposed to be within 2 'markers' within a document. The markers
are '---' on a line by itself and ',,,' on a line by itself. These
2 markers mark the beginning and end of the assembly program
within the document. Also the cursor needs to be between
these 2 markers.
compile an avr assembly program within a document to 'test.hex'
map ;ac :?^ *---?+1,/,,,/-1w ! ( cat - ) > test.asm; avra test.asm;
compile source and upload to the arduino 'duemilanove' board
map ;av :?^ *---?+1,/,,,/-1w ! ( cat - ) > test.asm; avra test.asm; sudo avrdude -p atmega328p -carduino -P/dev/ttyUSB0 -b57600 -D -Uflash:w:test.hex:i
The following is useful for determining how much space is
left within a boot file (which is limited to 512 bytes)
see how big a compiled file is without running it
map ;ab :?^ *---?+1,/,,,/-1w ! ( cat - ) > test.asm; avra test.asm; ls -la
DOCUMENT-NOTES: