Skip to content

Commit fdb97ed

Browse files
authored
Add microcontroller.cpu.temperature, for use as a simple sensor on minimal boards. (adafruit#211)
* Add microcontroller.cpu, the sole instance of microcontroller.Processor. microcontroller.cpu.frequency is the clock frequency, in Hz. microcontroller.cpu.temperature is the reading from the internal temperature sensor, in Celsius. None if not available. * Squeeze firmware size by using -finline-limit. Otherwise non-Express builds were slightly too big. * Update submodules. * Fix documentation glitches
1 parent f3cd6b0 commit fdb97ed

File tree

16 files changed

+599
-21
lines changed

16 files changed

+599
-21
lines changed

atmel-samd/Makefile

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,9 @@ ifeq ($(DEBUG), 1)
135135
# -DMICROPY_DEBUG_MODULES may also be added to an -flto build, if you wish.
136136
CFLAGS += -Os -ggdb -DNDEBUG -DENABLE_MICRO_TRACE_BUFFER -DMICROPY_DEBUG_MODULES
137137
else
138-
CFLAGS += -Os -DNDEBUG -flto
138+
# -finline-limit can shrink the image size. -finline-limit=80 or so is similar to not having it on.
139+
# There is no simple default value, though.
140+
CFLAGS += -Os -DNDEBUG -flto -finline-limit=57
139141
endif
140142

141143
ifneq ($(FROZEN_DIR),)
@@ -248,6 +250,7 @@ SRC_COMMON_HAL = \
248250
digitalio/DigitalInOut.c \
249251
microcontroller/__init__.c \
250252
microcontroller/Pin.c \
253+
microcontroller/Processor.c \
251254
neopixel_write/__init__.c \
252255
nvm/__init__.c \
253256
nvm/ByteArray.c \
Lines changed: 235 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,235 @@
1+
/*
2+
* This file is part of the MicroPython project, http://micropython.org/
3+
*
4+
* The MIT License (MIT)
5+
*
6+
* Copyright (c) 2017 Dan Halbert for Adafruit Industries
7+
*
8+
* Permission is hereby granted, free of charge, to any person obtaining a copy
9+
* of this software and associated documentation files (the "Software"), to deal
10+
* in the Software without restriction, including without limitation the rights
11+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12+
* copies of the Software, and to permit persons to whom the Software is
13+
* furnished to do so, subject to the following conditions:
14+
*
15+
* The above copyright notice and this permission notice shall be included in
16+
* all copies or substantial portions of the Software.
17+
*
18+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24+
* THE SOFTWARE.
25+
*/
26+
27+
/*
28+
* Includes code from ASF sample code adc_temp.h and adc_temp.c,
29+
* and so includes this license:
30+
*
31+
* Copyright (C) 2015 Atmel Corporation. All rights reserved.
32+
*
33+
* License
34+
*
35+
* Redistribution and use in source and binary forms, with or without
36+
* modification, are permitted provided that the following conditions are met:
37+
*
38+
* 1. Redistributions of source code must retain the above copyright notice,
39+
* this list of conditions and the following disclaimer.
40+
*
41+
* 2. Redistributions in binary form must reproduce the above copyright notice,
42+
* this list of conditions and the following disclaimer in the documentation
43+
* and/or other materials provided with the distribution.
44+
*
45+
* 3. The name of Atmel may not be used to endorse or promote products derived
46+
* from this software without specific prior written permission.
47+
*
48+
* 4. This software may only be redistributed and used in connection with an
49+
* Atmel microcontroller product.
50+
*
51+
* THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
52+
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
53+
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
54+
* EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
55+
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
56+
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
57+
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
58+
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
59+
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
60+
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
61+
* POSSIBILITY OF SUCH DAMAGE.
62+
*/
63+
64+
#include "common-hal/microcontroller/Processor.h"
65+
66+
// Don't reorder these includes because they are dependencies of adc_feature.h.
67+
// They should really be included by adc_feature.h.
68+
#include <compiler.h>
69+
#include "asf/sam0/drivers/system/clock/gclk.h"
70+
#include "asf/sam0/utils/cmsis/samd21/include/component/adc.h"
71+
72+
#include "asf/sam0/drivers/adc/adc_sam_d_r/adc_feature.h"
73+
#include "asf/sam0/drivers/adc/adc.h"
74+
75+
#define ADC_TEMP_SAMPLE_LENGTH 4
76+
#define INT1V_VALUE_FLOAT 1.0
77+
#define INT1V_DIVIDER_1000 1000.0
78+
#define ADC_12BIT_FULL_SCALE_VALUE_FLOAT 4095.0
79+
80+
typedef struct nvm_calibration_data_t {
81+
float tempR; // Production Room temperature
82+
float tempH; // Production Hot temperature
83+
float INT1VR; // Room temp 2's complement of the internal 1V reference value
84+
float INT1VH; // Hot temp 2's complement of the internal 1V reference value
85+
uint16_t ADCR; // Production Room temperature ADC value
86+
uint16_t ADCH; // Production Hot temperature ADC value
87+
float VADCR; // Room temperature ADC voltage
88+
float VADCH; // Hot temperature ADC voltage
89+
} nvm_calibration_data_t;
90+
91+
92+
// Decimal to fraction conversion. (adapted from ASF sample).
93+
STATIC float convert_dec_to_frac(uint8_t val) {
94+
float float_val = (float)val;
95+
if (val < 10) {
96+
return (float_val/10.0);
97+
} else if (val < 100) {
98+
return (float_val/100.0);
99+
} else {
100+
return (float_val/1000.0);
101+
}
102+
}
103+
104+
STATIC void configure_adc_temp(struct adc_module *adc_instance) {
105+
struct adc_config config_adc;
106+
adc_get_config_defaults(&config_adc);
107+
108+
// The parameters chosen here are from the temperature example in:
109+
// http://www.atmel.com/images/Atmel-42645-ADC-Configurations-with-Examples_ApplicationNote_AT11481.pdf
110+
// That note also recommends in general:
111+
// "Discard the first conversion result whenever there is a change
112+
// in ADC configuration like voltage reference / ADC channel change."
113+
114+
config_adc.clock_prescaler = ADC_CLOCK_PRESCALER_DIV16;
115+
config_adc.reference = ADC_REFERENCE_INT1V;
116+
config_adc.positive_input = ADC_POSITIVE_INPUT_TEMP;
117+
config_adc.negative_input = ADC_NEGATIVE_INPUT_GND;
118+
config_adc.sample_length = ADC_TEMP_SAMPLE_LENGTH;
119+
120+
adc_init(adc_instance, ADC, &config_adc);
121+
122+
// Oversample and decimate. A higher samplenum produces a more stable result.
123+
ADC->AVGCTRL.reg = ADC_AVGCTRL_ADJRES(2) | ADC_AVGCTRL_SAMPLENUM_4;
124+
//ADC->AVGCTRL.reg = ADC_AVGCTRL_ADJRES(4) | ADC_AVGCTRL_SAMPLENUM_16;
125+
}
126+
127+
// Extract the production calibration data information from NVM (adapted from ASF sample).
128+
//
129+
STATIC void load_calibration_data(nvm_calibration_data_t *cal) {
130+
volatile uint32_t val1; /* Temperature Log Row Content first 32 bits */
131+
volatile uint32_t val2; /* Temperature Log Row Content another 32 bits */
132+
uint8_t room_temp_val_int; /* Integer part of room temperature in °C */
133+
uint8_t room_temp_val_dec; /* Decimal part of room temperature in °C */
134+
uint8_t hot_temp_val_int; /* Integer part of hot temperature in °C */
135+
uint8_t hot_temp_val_dec; /* Decimal part of hot temperature in °C */
136+
int8_t room_int1v_val; /* internal 1V reference drift at room temperature */
137+
int8_t hot_int1v_val; /* internal 1V reference drift at hot temperature*/
138+
139+
uint32_t *temp_log_row_ptr = (uint32_t *)NVMCTRL_TEMP_LOG;
140+
141+
val1 = *temp_log_row_ptr;
142+
temp_log_row_ptr++;
143+
val2 = *temp_log_row_ptr;
144+
145+
room_temp_val_int = (uint8_t)((val1 & NVMCTRL_FUSES_ROOM_TEMP_VAL_INT_Msk) >> NVMCTRL_FUSES_ROOM_TEMP_VAL_INT_Pos);
146+
room_temp_val_dec = (uint8_t)((val1 & NVMCTRL_FUSES_ROOM_TEMP_VAL_DEC_Msk) >> NVMCTRL_FUSES_ROOM_TEMP_VAL_DEC_Pos);
147+
148+
hot_temp_val_int = (uint8_t)((val1 & NVMCTRL_FUSES_HOT_TEMP_VAL_INT_Msk) >> NVMCTRL_FUSES_HOT_TEMP_VAL_INT_Pos);
149+
hot_temp_val_dec = (uint8_t)((val1 & NVMCTRL_FUSES_HOT_TEMP_VAL_DEC_Msk) >> NVMCTRL_FUSES_HOT_TEMP_VAL_DEC_Pos);
150+
151+
room_int1v_val = (int8_t)((val1 & NVMCTRL_FUSES_ROOM_INT1V_VAL_Msk) >> NVMCTRL_FUSES_ROOM_INT1V_VAL_Pos);
152+
hot_int1v_val = (int8_t)((val2 & NVMCTRL_FUSES_HOT_INT1V_VAL_Msk) >> NVMCTRL_FUSES_HOT_INT1V_VAL_Pos);
153+
154+
cal->ADCR = (uint16_t)((val2 & NVMCTRL_FUSES_ROOM_ADC_VAL_Msk) >> NVMCTRL_FUSES_ROOM_ADC_VAL_Pos);
155+
156+
cal->ADCH = (uint16_t)((val2 & NVMCTRL_FUSES_HOT_ADC_VAL_Msk) >> NVMCTRL_FUSES_HOT_ADC_VAL_Pos);
157+
158+
cal->tempR = room_temp_val_int + convert_dec_to_frac(room_temp_val_dec);
159+
cal->tempH = hot_temp_val_int + convert_dec_to_frac(hot_temp_val_dec);
160+
161+
cal->INT1VR = 1 - ((float)room_int1v_val/INT1V_DIVIDER_1000);
162+
cal->INT1VH = 1 - ((float)hot_int1v_val/INT1V_DIVIDER_1000);
163+
164+
cal->VADCR = ((float)cal->ADCR * cal->INT1VR)/ADC_12BIT_FULL_SCALE_VALUE_FLOAT;
165+
cal->VADCH = ((float)cal->ADCH * cal->INT1VH)/ADC_12BIT_FULL_SCALE_VALUE_FLOAT;
166+
}
167+
168+
/*
169+
* Calculate fine temperature using Equation1 and Equation
170+
* 1b as mentioned in data sheet section "Temperature Sensor Characteristics"
171+
* of Electrical Characteristics. (adapted from ASF sample code).
172+
*/
173+
STATIC float calculate_temperature(uint16_t raw_code, nvm_calibration_data_t *cal)
174+
{
175+
float VADC; /* Voltage calculation using ADC result for Coarse Temp calculation */
176+
float VADCM; /* Voltage calculation using ADC result for Fine Temp calculation. */
177+
float INT1VM; /* Voltage calculation for reality INT1V value during the ADC conversion */
178+
179+
VADC = ((float)raw_code * INT1V_VALUE_FLOAT)/ADC_12BIT_FULL_SCALE_VALUE_FLOAT;
180+
181+
// Hopefully compiler will remove common subepxressions here.
182+
183+
/* Coarse Temp Calculation by assume INT1V=1V for this ADC conversion */
184+
float coarse_temp = cal->tempR + (((cal->tempH - cal->tempR)/(cal->VADCH - cal->VADCR)) * (VADC - cal->VADCR));
185+
186+
/* Calculation to find the real INT1V value during the ADC conversion */
187+
INT1VM = cal->INT1VR + (((cal->INT1VH - cal->INT1VR) * (coarse_temp - cal->tempR))/(cal->tempH - cal->tempR));
188+
189+
VADCM = ((float)raw_code * INT1VM)/ADC_12BIT_FULL_SCALE_VALUE_FLOAT;
190+
191+
/* Fine Temp Calculation by replace INT1V=1V by INT1V = INT1Vm for ADC conversion */
192+
float fine_temp = cal->tempR + (((cal->tempH - cal->tempR)/(cal->VADCH - cal->VADCR)) * (VADCM - cal->VADCR));
193+
194+
return fine_temp;
195+
}
196+
197+
198+
// External interface.
199+
//
200+
float common_hal_mcu_processor_get_temperature(void) {
201+
struct adc_module adc_instance_struct;
202+
203+
system_voltage_reference_enable(SYSTEM_VOLTAGE_REFERENCE_TEMPSENSE);
204+
configure_adc_temp(&adc_instance_struct);
205+
nvm_calibration_data_t nvm_calibration_data;
206+
load_calibration_data(&nvm_calibration_data);
207+
208+
adc_enable(&adc_instance_struct);
209+
210+
uint16_t data;
211+
enum status_code status;
212+
213+
// Read twice and discard first result, as recommended in section 14 of
214+
// http://www.atmel.com/images/Atmel-42645-ADC-Configurations-with-Examples_ApplicationNote_AT11481.pdf
215+
// "Discard the first conversion result whenever there is a change in ADC configuration
216+
// like voltage reference / ADC channel change"
217+
// Empirical observation shows the first reading is quite different than subsequent ones.
218+
219+
adc_start_conversion(&adc_instance_struct);
220+
do {
221+
status = adc_read(&adc_instance_struct, &data);
222+
} while (status == STATUS_BUSY);
223+
224+
adc_start_conversion(&adc_instance_struct);
225+
do {
226+
status = adc_read(&adc_instance_struct, &data);
227+
} while (status == STATUS_BUSY);
228+
229+
return calculate_temperature(data, &nvm_calibration_data);
230+
}
231+
232+
233+
uint32_t common_hal_mcu_processor_get_frequency(void) {
234+
return system_cpu_clock_get_hz();
235+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/*
2+
* This file is part of the MicroPython project, http://micropython.org/
3+
*
4+
* The MIT License (MIT)
5+
*
6+
* Copyright (c) 2017 Dan Halbert for Adafruit Industries
7+
*
8+
* Permission is hereby granted, free of charge, to any person obtaining a copy
9+
* of this software and associated documentation files (the "Software"), to deal
10+
* in the Software without restriction, including without limitation the rights
11+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12+
* copies of the Software, and to permit persons to whom the Software is
13+
* furnished to do so, subject to the following conditions:
14+
*
15+
* The above copyright notice and this permission notice shall be included in
16+
* all copies or substantial portions of the Software.
17+
*
18+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24+
* THE SOFTWARE.
25+
*/
26+
27+
#ifndef MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_MICROCONTROLLER_PROCESSOR_H
28+
#define MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_MICROCONTROLLER_PROCESSOR_H
29+
30+
#include "py/obj.h"
31+
32+
typedef struct {
33+
mp_obj_base_t base;
34+
// Stores no state currently.
35+
} mcu_processor_obj_t;
36+
37+
#endif // MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_MICROCONTROLLER_PROCESSOR_H

atmel-samd/common-hal/microcontroller/__init__.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#include "samd21_pins.h"
3131

3232
#include "shared-bindings/nvm/ByteArray.h"
33+
#include "shared-bindings/microcontroller/Processor.h"
3334

3435
void common_hal_mcu_delay_us(uint32_t delay) {
3536
mp_hal_delay_us(delay);
@@ -50,8 +51,17 @@ void common_hal_mcu_enable_interrupts(void) {
5051
cpu_irq_restore(irq_flags);
5152
}
5253

54+
// The singleton microcontroller.Processor object, bound to microcontroller.cpu
55+
// It currently only has properties, and no state.
56+
mcu_processor_obj_t common_hal_mcu_processor_obj = {
57+
.base = {
58+
.type = &mcu_processor_type,
59+
},
60+
};
61+
5362
// NVM is only available on Express boards for now.
5463
#if CIRCUITPY_INTERNAL_NVM_SIZE > 0
64+
// The singleton nvm.ByteArray object.
5565
nvm_bytearray_obj_t common_hal_mcu_nvm_obj = {
5666
.base = {
5767
.type = &nvm_bytearray_type,

atmel-samd/common-hal/nvm/__init__.c

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,27 @@
1+
/*
2+
* This file is part of the MicroPython project, http://micropython.org/
3+
*
4+
* The MIT License (MIT)
5+
*
6+
* Copyright (c) 2017 Scott Shawcroft for Adafruit Industries
7+
*
8+
* Permission is hereby granted, free of charge, to any person obtaining a copy
9+
* of this software and associated documentation files (the "Software"), to deal
10+
* in the Software without restriction, including without limitation the rights
11+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12+
* copies of the Software, and to permit persons to whom the Software is
13+
* furnished to do so, subject to the following conditions:
14+
*
15+
* The above copyright notice and this permission notice shall be included in
16+
* all copies or substantial portions of the Software.
17+
*
18+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24+
* THE SOFTWARE.
25+
*/
26+
127
// No nvm module functions.

esp8266/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ SRC_C = \
101101
SRC_COMMON_HAL = \
102102
microcontroller/__init__.c \
103103
microcontroller/Pin.c \
104+
microcontroller/Processor.c \
104105
analogio/__init__.c \
105106
analogio/AnalogIn.c \
106107
analogio/AnalogOut.c \
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/*
2+
* This file is part of the MicroPython project, http://micropython.org/
3+
*
4+
* The MIT License (MIT)
5+
*
6+
* Copyright (c) 2017 Dan Halbert for Adafruit Industries
7+
*
8+
* Permission is hereby granted, free of charge, to any person obtaining a copy
9+
* of this software and associated documentation files (the "Software"), to deal
10+
* in the Software without restriction, including without limitation the rights
11+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12+
* copies of the Software, and to permit persons to whom the Software is
13+
* furnished to do so, subject to the following conditions:
14+
*
15+
* The above copyright notice and this permission notice shall be included in
16+
* all copies or substantial portions of the Software.
17+
*
18+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24+
* THE SOFTWARE.
25+
*/
26+
27+
#include "common-hal/microcontroller/Processor.h"
28+
29+
#include <math.h>
30+
31+
#include "esp_mphal.h"
32+
33+
34+
float common_hal_mcu_processor_get_temperature(void) {
35+
return NAN;
36+
}
37+
38+
uint32_t common_hal_mcu_processor_get_frequency(void) {
39+
return mp_hal_get_cpu_freq();
40+
}

0 commit comments

Comments
 (0)