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.