From 40f834d58fee1daa406f0f9edf01e393b3eb7f76 Mon Sep 17 00:00:00 2001 From: Ron Evans Date: Tue, 18 Sep 2018 15:02:38 +0200 Subject: [PATCH] avr: ADC with 0-1023 range --- src/examples/adc/adc.go | 29 +++++++++++++++++++++++ src/examples/serial/serial.go | 10 -------- src/machine/machine.go | 4 ++++ src/machine/machine_avr.go | 44 +++++++++++++++++++++++++++++++++++ 4 files changed, 77 insertions(+), 10 deletions(-) create mode 100644 src/examples/adc/adc.go delete mode 100644 src/examples/serial/serial.go diff --git a/src/examples/adc/adc.go b/src/examples/adc/adc.go new file mode 100644 index 00000000..8d1a9f4d --- /dev/null +++ b/src/examples/adc/adc.go @@ -0,0 +1,29 @@ +package main + +import ( + "machine" + "time" +) + +// This example assumes that an analog sensor such as a rotary dial is connected to pin ADC0. +// When the dial is turned past the midway point, the built-in LED will light up. + +func main() { + machine.InitADC() + + led := machine.GPIO{machine.LED} + led.Configure(machine.GPIOConfig{Mode: machine.GPIO_OUTPUT}) + + sensor := machine.ADC{machine.ADC2} + sensor.Configure() + + for { + val := sensor.Get() + if val < 512 { + led.Low() + } else { + led.High() + } + time.Sleep(time.Millisecond * 100) + } +} diff --git a/src/examples/serial/serial.go b/src/examples/serial/serial.go deleted file mode 100644 index b0dd403f..00000000 --- a/src/examples/serial/serial.go +++ /dev/null @@ -1,10 +0,0 @@ -package main - -import "time" - -func main() { - for { - println("hello world!") - time.Sleep(time.Second) - } -} diff --git a/src/machine/machine.go b/src/machine/machine.go index bc8e14cd..094b4b59 100644 --- a/src/machine/machine.go +++ b/src/machine/machine.go @@ -19,3 +19,7 @@ func (p GPIO) Low() { type PWM struct { Pin uint8 } + +type ADC struct { + Pin uint8 +} diff --git a/src/machine/machine_avr.go b/src/machine/machine_avr.go index dd46f15a..d338af1d 100644 --- a/src/machine/machine_avr.go +++ b/src/machine/machine_avr.go @@ -124,3 +124,47 @@ func (pwm PWM) Set(value uint16) { panic("Invalid PWM pin") } } + +// ADC on the Arduino +const ( + ADC0 = 0 + ADC1 = 1 + ADC2 = 2 + ADC3 = 3 + ADC4 = 4 + ADC5 = 5 +) + +// InitADC initializes the registers needed for ADC. +func InitADC() { + // set a2d prescaler so we are inside the desired 50-200 KHz range at 16MHz. + *avr.ADCSRA |= (avr.ADCSRA_ADPS2 | avr.ADCSRA_ADPS1 | avr.ADCSRA_ADPS0) + + // enable a2d conversions + *avr.ADCSRA |= avr.ADCSRA_ADEN +} + +// Configure configures a ADCPin to be able to be used to read data. +func (a ADC) Configure() { + return // no pin specific setup on AVR machine. +} + +// Get returns the current value of a ADC pin. The AVR will return a 10bit value ranging +// from 0-1023. +func (a ADC) Get() uint16 { + // set the analog reference (high two bits of ADMUX) and select the + // channel (low 4 bits), masked to only turn on one ADC at a time. + // this also sets ADLAR (left-adjust result) to 0 (the default). + *avr.ADMUX = avr.RegValue(avr.ADMUX_REFS0 | (a.Pin & 0x07)) + + // start the conversion + *avr.ADCSRA |= avr.ADCSRA_ADSC + + // ADSC is cleared when the conversion finishes + for ok := true; ok; ok = (*avr.ADCSRA & avr.ADCSRA_ADSC) > 0 { + } + + low := uint16(*avr.ADCL) + high := uint16(*avr.ADCH) + return uint16(low) | uint16(high<<8) +}