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.
Этот коммит содержится в:
Ayke van Laethem 2022-09-18 22:56:11 +02:00 коммит произвёл Ron Evans
родитель 86ea216e7d
коммит 70b3ece6ec
4 изменённых файлов: 39 добавлений и 64 удалений

Просмотреть файл

@ -611,7 +611,7 @@ endif
@$(MD5SUM) test.hex @$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=challenger-rp2040 examples/blinky1 $(TINYGO) build -size short -o test.hex -target=challenger-rp2040 examples/blinky1
@$(MD5SUM) test.hex @$(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 @$(MD5SUM) test.hex
# test pwm # test pwm
$(TINYGO) build -size short -o test.hex -target=itsybitsy-m0 examples/pwm $(TINYGO) build -size short -o test.hex -target=itsybitsy-m0 examples/pwm

Просмотреть файл

@ -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)
}
}

23
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)
}
}

Просмотреть файл

@ -17,8 +17,8 @@ const (
adc0_CH ADCChannel = iota adc0_CH ADCChannel = iota
adc1_CH adc1_CH
adc2_CH adc2_CH
adc3_CH // Note: GPIO29 not broken out on pico board adc3_CH // Note: GPIO29 not broken out on pico board
ADC_TEMP_SENSOR // Internal temperature sensor channel adcTempSensor // Internal temperature sensor channel
) )
// Used to serialise ADC sampling // Used to serialise ADC sampling
@ -75,19 +75,17 @@ func (a ADC) GetADCChannel() (c ADCChannel, err error) {
return c, err 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. // The powered on temperature sensor increases ADC_AVDD current by approximately 40 μA.
func (c ADCChannel) Configure(config ADCConfig) error { func (c ADCChannel) Configure(config ADCConfig) error {
if config.Reference != 0 { if config.Reference != 0 {
adcAref = config.Reference adcAref = config.Reference
} }
if p, err := c.Pin(); err == nil { p, err := c.Pin()
p.Configure(PinConfig{Mode: PinAnalog}) if err != nil {
} return err
if c == ADC_TEMP_SENSOR {
// Enable temperature sensor bias source
rp.ADC.CS.SetBits(rp.ADC_CS_TS_EN)
} }
p.Configure(PinConfig{Mode: PinAnalog})
return nil 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. // 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 ReadTemperature() (millicelsius int32) {
func (c ADCChannel) ReadTemperature() (millicelsius uint32) { if rp.ADC.CS.Get()&rp.ADC_CS_EN == 0 {
if c != ADC_TEMP_SENSOR { InitADC()
return
} }
// Enable temperature sensor bias source
rp.ADC.CS.SetBits(rp.ADC_CS_TS_EN)
// T = 27 - (ADC_voltage - 0.706)/0.001721 // 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. // waitForReady spins waiting for the ADC peripheral to become ready.