From 70b3ece6ec5583e7db749c49a3bdc08d158a24ad Mon Sep 17 00:00:00 2001 From: Ayke van Laethem Date: Sun, 18 Sep 2022 22:56:11 +0200 Subject: [PATCH] rp2040: add machine.ReadTemperature Replace ADCChannel.ReadTemperature() with a simple ReadTemperature function. Not all chips will have a temperature sensor that is read by sampling an ADC channel. The replacement ReadTemperature is simpler and more generic to other chip families. This breaks chips that were relying on the previous ReadTemperature method. I hope it won't break a lot of existing code. If it does, a fallback can be added. --- Makefile | 2 +- src/examples/adc_rp2040/adc.go | 49 ------------------------------- src/examples/temp/temp.go | 23 +++++++++++++++ src/machine/machine_rp2040_adc.go | 29 +++++++++--------- 4 files changed, 39 insertions(+), 64 deletions(-) delete mode 100644 src/examples/adc_rp2040/adc.go create mode 100644 src/examples/temp/temp.go diff --git a/Makefile b/Makefile index 4e1247bd..f724173f 100644 --- a/Makefile +++ b/Makefile @@ -611,7 +611,7 @@ endif @$(MD5SUM) test.hex $(TINYGO) build -size short -o test.hex -target=challenger-rp2040 examples/blinky1 @$(MD5SUM) test.hex - $(TINYGO) build -size short -o test.hex -target=trinkey-qt2040 examples/adc_rp2040 + $(TINYGO) build -size short -o test.hex -target=trinkey-qt2040 examples/temp @$(MD5SUM) test.hex # test pwm $(TINYGO) build -size short -o test.hex -target=itsybitsy-m0 examples/pwm diff --git a/src/examples/adc_rp2040/adc.go b/src/examples/adc_rp2040/adc.go deleted file mode 100644 index ef0e2d40..00000000 --- a/src/examples/adc_rp2040/adc.go +++ /dev/null @@ -1,49 +0,0 @@ -// Reads multiple rp2040 ADC channels concurrently. Including the internal temperature sensor - -package main - -import ( - "fmt" - "machine" - "time" -) - -type celsius float32 - -func (c celsius) String() string { - return fmt.Sprintf("%4.1f℃", c) -} - -// rp2040 ADC is 12 bits. Reading are shifted <<4 to fill the 16-bit range. -var adcReading [3]uint16 - -func readADC(a machine.ADC, w time.Duration, i int) { - for { - adcReading[i] = a.Get() - time.Sleep(w) - } -} - -func main() { - machine.InitADC() - a0 := machine.ADC{machine.ADC0} // GPIO26 input - a1 := machine.ADC{machine.ADC1} // GPIO27 input - a2 := machine.ADC{machine.ADC2} // GPIO28 input - t := machine.ADC_TEMP_SENSOR // Internal Temperature sensor - // Configure sets the GPIOs to PinAnalog mode - a0.Configure(machine.ADCConfig{}) - a1.Configure(machine.ADCConfig{}) - a2.Configure(machine.ADCConfig{}) - // Configure powers on the temperature sensor - t.Configure(machine.ADCConfig{}) - - // Safe to read concurrently - go readADC(a0, 10*time.Millisecond, 0) - go readADC(a1, 17*time.Millisecond, 1) - go readADC(a2, 29*time.Millisecond, 2) - - for { - fmt.Printf("ADC0: %5d ADC1: %5d ADC2: %5d Temp: %v\n\r", adcReading[0], adcReading[1], adcReading[2], celsius(float32(t.ReadTemperature())/1000)) - time.Sleep(1000 * time.Millisecond) - } -} diff --git a/src/examples/temp/temp.go b/src/examples/temp/temp.go new file mode 100644 index 00000000..92f147fb --- /dev/null +++ b/src/examples/temp/temp.go @@ -0,0 +1,23 @@ +// Read the internal temperature sensor of the chip. + +package main + +import ( + "fmt" + "machine" + "time" +) + +type celsius float32 + +func (c celsius) String() string { + return fmt.Sprintf("%4.1f℃", c) +} + +func main() { + for { + temp := celsius(float32(machine.ReadTemperature()) / 1000) + println("temperature:", temp.String()) + time.Sleep(time.Second) + } +} diff --git a/src/machine/machine_rp2040_adc.go b/src/machine/machine_rp2040_adc.go index 97a54c67..38ba4cf8 100644 --- a/src/machine/machine_rp2040_adc.go +++ b/src/machine/machine_rp2040_adc.go @@ -17,8 +17,8 @@ const ( adc0_CH ADCChannel = iota adc1_CH adc2_CH - adc3_CH // Note: GPIO29 not broken out on pico board - ADC_TEMP_SENSOR // Internal temperature sensor channel + adc3_CH // Note: GPIO29 not broken out on pico board + adcTempSensor // Internal temperature sensor channel ) // Used to serialise ADC sampling @@ -75,19 +75,17 @@ func (a ADC) GetADCChannel() (c ADCChannel, err error) { return c, err } -// Configure sets the channel's associated pin to analog input mode or powers on the temperature sensor for ADC_TEMP_SENSOR. +// Configure sets the channel's associated pin to analog input mode. // The powered on temperature sensor increases ADC_AVDD current by approximately 40 μA. func (c ADCChannel) Configure(config ADCConfig) error { if config.Reference != 0 { adcAref = config.Reference } - if p, err := c.Pin(); err == nil { - p.Configure(PinConfig{Mode: PinAnalog}) - } - if c == ADC_TEMP_SENSOR { - // Enable temperature sensor bias source - rp.ADC.CS.SetBits(rp.ADC_CS_TS_EN) + p, err := c.Pin() + if err != nil { + return err } + p.Configure(PinConfig{Mode: PinAnalog}) return nil } @@ -112,13 +110,16 @@ func (c ADCChannel) getVoltage() uint32 { } // ReadTemperature does a one-shot sample of the internal temperature sensor and returns a milli-celsius reading. -// Only works on the ADC_TEMP_SENSOR channel. aka AINSEL=4. Other channels will return 0 -func (c ADCChannel) ReadTemperature() (millicelsius uint32) { - if c != ADC_TEMP_SENSOR { - return +func ReadTemperature() (millicelsius int32) { + if rp.ADC.CS.Get()&rp.ADC_CS_EN == 0 { + InitADC() } + + // Enable temperature sensor bias source + rp.ADC.CS.SetBits(rp.ADC_CS_TS_EN) + // T = 27 - (ADC_voltage - 0.706)/0.001721 - return (27000<<16 - (c.getVoltage()-706<<16)*581) >> 16 + return (27000<<16 - (int32(adcTempSensor.getVoltage())-706<<16)*581) >> 16 } // waitForReady spins waiting for the ADC peripheral to become ready.