2021年11月18日星期四

[Arduino] analogRead應用-使用熱敏電阻量測溫度-查表法

Arduino NTC

什麼是熱敏電阻?

熱敏電阻是個傳感器,特性是電阻值會隨著溫度變化而改變。這個元件其實很古老了,早期在電源類的產品中常用的元件之一,最主要的運用是用來偵測元件運作溫度。現在大部分設計為了要求精密度更高,新設計通常會使用晶片的形式來偵測溫度。

熱敏電阻大致分為兩種,

電阻值隨溫度上升而增加,為正溫度係數 (Positive Temperature Coefficient,簡稱 PTC)
電阻值隨溫度上升而減少,為負溫度係數 (Negative Temperature Coefficient,簡稱 NTC)

PTC 型的熱敏電阻,通常應用在電路保護的 可復式保險絲。例如:PolySwitch,如果發生電路過流現象會依據設計範圍內,使得溫度上升而阻抗變高,最後形成斷路現象。

這次應用的是 NTC的熱敏電阻用來檢測溫度。使用時必須固定在要檢測的會發熱的元件目標物上。

實體元件

Arduino NTC

規格 : 25度常溫 10KOhm ,誤差:正負 1% ,通常需要廠家提供參數值。

紅色框是溫度,藍色框是該溫度時的電阻值。左右兩邊是誤差範圍,我取的是中間值

電路設計

電路由電阻分壓方式組成,產生分壓電壓後再利用公式推算目前溫度所在。

Arduino NTC


程式碼


#define THSourceVoltage 5.0
#define THRES       7500


const int analogPin = A0;
int value;


unsigned int temptable[] = {8019,7679,7356,7048,6754,6475,6209,5956,5714,5484,
                                    5264,5055,4855,4664,4482,4308,4143,3984,3833,3688,
                                    3549,3417,3291,3170,3054,2943,2837,2735,2637,2544,
                                    2455,2369,2286,2207,2132,2059,1989,1922,1858,1796,
                                    1736,1679,1624,1571,1521,1472,1425,1379,1336,1294,
                                    1253,1214,1176,1140,1105,1072,1039,1008,977,948,
                                    920,893,867,841,817,793,770,748,727,706,
                                    686,667,649,631,613,596};


unsigned char temp;
                                    
void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
}


void loop() {
  // put your main code here, to run repeatedly:
  value = analogRead(analogPin);
  temp = calTemp((THSourceVoltage * value)/1023);
  Serial.print("NTC temp: ");
  Serial.println(temp);
  Serial.println("");  
  delay(1000);
}




float calVoltage(unsigned int value)
{
  return THSourceVoltage * value/(value + THRES);
}


unsigned char calTemp(float value)
{
  unsigned char x,res;
  float xc;
  for(x = 0; x < sizeof(temptable)/sizeof(unsigned int); x++)
  {
    xc = calVoltage(temptable[x]);
    if(xc <= value)
    {
      res = 1;
      break;
    }
  }


  if(res)
    return (30 + x);


  return 0;  
}

temptable 陣列的範圍是 30度 到最高溫度 105 度。透過 calVoltage function 及 for 迴圈比對,就可以順利得知溫度了

我用手指緊捏 NTC 的 顯示結果

Arduino NTC

目前手指溫度 35 度哦。用分壓電路組成的電路大概會有約 2%~3%的誤差範圍 ,這個結果其實也不差。 用在允許有誤差溫度範圍及低成本下,也是可以使用選擇的方式之一。

原始碼連結

https://github.com/cold63/Arduino_Code/tree/main/NTCTemp

相關參考

使用熱敏電阻量測溫度 -斯坦哈特-哈特公式
https://www.makdev.net/2021/11/arduino-analogread-model-func.html

analogRead 基礎
https://www.makdev.net/2020/12/arduino-analogread.html

Voltage Divider Calculator 電阻分壓計算
https://www.makdev.net/p/voltage-divider-calculator.html

[Arduino] analogRead應用-使用熱敏電阻量測溫度 -斯坦哈特-哈特公式

前提概要

前次使用 使用熱敏電阻量測溫度 - 查表法... 測量熱敏電阻溫度,這次使用同樣的熱敏電阻及電路,使用 Steinhart–Hart equation (斯坦哈特-哈特公式) 計算熱敏電阻所得到的溫度。
Steinhart–Hart 是兩個人 ,John S. Steinhart 及 Stanley R. Hart。他們利用 NTC 測量海洋溫度時所提出的公式。等式為

1/T = A+Bln R+ C(ln R)^3

T 是溫度 ,單位是 kelvin
R 是電阻值
A,B,C 常數

要利用這個推導公式最少需要 3 組已知的電阻值,這在後面會提到。
詳細內容可參考 wiki (https://en.wikipedia.org/wiki/Steinhart-Hart_equation)

另位,會使用一個溫度單位 kelvin 。它是一種溫度的國際單位,表示符號為 K 。有些量測溫度功能的晶片也會使用這個國際單位。
詳細內容可參考 wiki (https://en.wikipedia.org/wiki/Kelvin)

同樣我們要拿出廠家提供的表格,找3個電阻值

RT0 : 常溫 25 度時的電阻值。
RT1 : 0 度時的電阻值。
RT2 : 105度時的電阻值。

所以,這次量測範圍是 0 ~ 105 度間。

Arduino NTC
Arduino NTC

同樣我們需要相對應的 K 值

T0 = 298.15 : 常溫 25度時的 Kelvin 值
T1 = 273.15 : 0度時的 Kelvin 值
T2 = 378.15 : 105度時的 Kelvin 值

這個可以利用 線上計算器 (https://www.rapidtables.com/convert/temperature/celsius-to-kelvin.html)


電路圖

一樣和使用查表法的電路相同

Arduino NTC

程式碼


#define THSourceVoltage 5.0
#define THRES       7500
#define RT0         10000  // 常溫 25度時的 NTC 電阻值
#define RT1         35563  // 0度時的 NTC 電阻值
#define RT2         596    // 105度時的 NTC 電阻值
#define T0          298.15 // 常溫 25度時的 Kelvin 值
#define T1          273.15 // 0度時的 Kelvin 值
#define T2          378.15 // 105度時的 Kelvin 值


const int analogPin = A0;
int value;
float VoltageOut;
float ROut;
float beta;
float Rx;
float KelvinValue;
                                   
void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);


  beta = (log(RT1/RT2))/((1/T1)-(1/T2));
  Rx = RT0 * exp(-beta/T0);
}


void loop() {
  // put your main code here, to run repeatedly:
  value = analogRead(analogPin);


  Serial.print("NTC Temp: ");
  
  VoltageOut = (THSourceVoltage * value)/1023;
  ROut = THRES * VoltageOut/ (THSourceVoltage - VoltageOut); //目前 NTC 電阻值
  KelvinValue=(beta/log(ROut/Rx));
  
  Serial.println(KelvinValue - 273.15); //Kelvin 轉 溫度C
  Serial.println("");  
  delay(1000);
}

同樣,我用手指緊捏 NTC 的 顯示結果

Arduino NTC

結果和查表法一樣是 35 度,這個方式更接近物理特性。後面再用軟體過濾器,數值就會更穩定及精確。

原始碼連結

https://github.com/cold63/Arduino_Code/tree/main/NTCTemp_modfunc

相關參考

使用熱敏電阻量測溫度-查表法
https://www.makdev.net/2021/11/arduino-analogread-lookup-table.html

analogRead 基礎
https://www.makdev.net/2020/12/arduino-analogread.html

Voltage Divider Calculator 電阻分壓計算
https://www.makdev.net/p/voltage-divider-calculator.html

2021年11月5日星期五

[STM32] ADC 轉換器 - 使用 DMA 多通道模式

 

STM32 ADC


緣起


針對前一篇的 Polling 多通道輪詢模式 方式做個簡單的比較。


基本設定


這次使用 NUCLEO-F401RE 開發版測試,執行 STM32CubeIDE 後直接進入 ADC1 設定項目,選擇其中 3 個 ADC Input 。

IN0    ->    PA0
IN1    ->    PA1
IN4    ->    PA4
STM32 ADC


DMA Settings 的標籤設定


先點取 Add ,選擇 ADC1

DMA Request Settings  的 Mode 選擇 Circular  ,連續DMA請求

STM32 ADC



Parameter Settings 標籤


Resoltion 維持 12 Bits 解析能力,也就是 0 ~ 4095 範圍。

Scan Conversion Mode 設定 Enabled 

Continuous Conversion Mode 設定 Enabled

DMA  Continuous Requests   設定  Enabled

Number Of Conversion 選擇 3 ,表示有 3 組ADC Iinput

Rank 要各自選擇 Channel

Sampling Time    這裡建議初步先設定最大值 480 Cycles

其他設定項目維持 Default 值。
STM32 ADC


儲存後 ,由 STM32CubeIDE 產生程式碼。


程式碼


打開 main.c

首先建立 2 個 Value


uint8_t x;
uint16_t ADCArray[3];

在 While 主迴圈之前啟動 ADC DMA , 最後的參數是指請求 DMA 時的資料筆數。目前設 3 個通道及陣列就直接設定 3 。這裡可以按照 3 的倍數擴大取得資料筆數,不過這裡先簡單使用。

if(HAL_ADC_Start_DMA(&hadc1,(uint32_t *)ADCArray,3) != HAL_OK)
{
       printf("ADC initialization error!\r\n");
}

while 主迴圈

  while (1)
  {
    /* USER CODE END WHILE */
         HAL_GPIO_TogglePin(LD2_GPIO_Port, LD2_Pin);
         printf("idx[%d] value[%d]\r\n",x,ADCArray[x] );
         x++;
         if(x >=3)
         {
               x = 0;
               printf("\r\n");
         }
         HAL_Delay(1000);
    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
3 組 ADC Input 的資料會自動儲存到記憶體也就是陣列裡。

好了,這樣就完成了。

簡易的測試方法是將剛剛設定的 ADC 腳位 ,分別接入 3.3V 。看看是否 print 的 值是否是 4095 。接地是否為 0 
在這裡陣列裡的資料會依序 Channel 0 ,Channel 1 , Channel 4 分別填入,這個就比 Polling 的方式方便了。
原始碼連結


相關連結

ADC 轉換器 - 使用 Polling 多通道輪詢模式

[STM32] ADC 轉換器 - 使用 Polling 多通道輪詢模式

 

STM32 ADC Polling

緣起

我想一開始在做 ADC 轉換這項功能時,要驗證時可能會從 輪詢方式 先著手吧。因為第一印象通常是比較容易達成,確實也是。實作時很快就有結果,拿著官方範例一步一步做好。官方是使用單通道做為基本範例。可是當時我的需求是多通道,經過一番測試仍然測試不出來。迫於時間因素就先改弦易轍,換了 ADC DMA 模式,其實也沒花太多時間研究也就實做出來。雖然,輪詢模式缺點是比較耗 MCU 資源,但是在心中覺得還想試試看放在心中的一個疑問。

基本設定


這次使用 NUCLEO-F401RE 開發版測試,執行 STM32CubeIDE 後直接進入 ADC1 設定項目,選擇其中 3 個 ADC Input 。

IN0    ->    PA0
IN1    ->    PA1
IN4    ->    PA4

STM32 ADC

Parameter Settings 標籤

Resoltion 維持 12 Bits 解析能力,也就是 0 ~ 4095 範圍。

Scan Conversion Mode 設定 Enabled 

Continuous Conversion Mode 設定 Enabled

Number Of Conversion 選擇 3 ,表示有 3 組ADC Iinput

Rank 要各自選擇 Channel

其他設定項目維持 Default 值。
STM32 ADC


儲存後 ,由 STM32CubeIDE 產生程式碼。


程式碼


打開 main.c 後,首先建立 readVoltage() function


uint16_t readVoltage()
{
       HAL_ADC_Start(&hadc1); /* 啟動 ADC 轉換*/
       /*     等待轉換完成 , 100 指 timout 時間。 單位 ms*/
       if(HAL_ADC_PollForConversion(&hadc1,100) == HAL_OK)
       {
              /*     確認轉換完成 Flag */
              if(HAL_IS_BIT_SET(HAL_ADC_GetState(&hadc1),HAL_ADC_STATE_REG_EOC))
              {
                     return (uint16_t)HAL_ADC_GetValue(&hadc1); /*讀取轉換數值 0 ~ 4095 之間*/
              }
       }
       return 0;
}
建立 2 個 Value
  uint8_t x;
  uint16_t ADValue[3];

到主 while 迴圈中

  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */
        HAL_GPIO_TogglePin(LD2_GPIO_Port, LD2_Pin);
        ADValue[x] = readVoltage();
        printf("idx[%d] value[%d]\r\n",x,ADValue[x] );
        x++;
        if(x >=3)
        {
               x = 0;
               printf("\r\n");
        }
         HAL_Delay(1000);
    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */

readVoltage() 讀到值後,會將 3 組 ADC Input 值儲存在 ADValue[3] 陣列裡。

好了,這樣就完成了。

簡易的測試方法是將剛剛設定的 ADC 腳位 ,分別接入 3.3V 。看看是否 print 的 值是否是接近 4095 。接地是否為 0 

不過,遇到一個不解的地方。以為 Polling 讀 ADC 值的時候,會按照 Channel 0 ,Channel 1 , Channel 4 按照這個順序。結果並不是,所以需要一個一個實際確認對應的 ADC Input 腳位及陣列的對應索引。這個問題不大,實務上本來就是需要各自確認 ADC 轉換有沒有工作正常。

原始碼連結
https://github.com/cold63/STM32_Code/tree/master/ADC_Polling



相關連結

ADC 轉換器 - 使用 DMA 多通道模式

2021年9月16日星期四

[Ameba] A1 PICO / RTL8720DN (BW16) 開發板 與 Arduino IDE

緣起

Realtek RTL8720DN 是一個具有 Wifi + Bluetooth 無線晶片, Wifi 且支援雙模 (802.11 a/b/g/n 1x1, 2.4GHz & 5GHz ) 和低功耗的 BLE 5。處理器內核採用 Dual processor core 設計 集成 ARM V8M Cortex-M33 (指令集相容於 Cortex-M4F) 及 ARM V8M Cortex-M23 (相容於 Cortex-M0+) 。 Wi-Fi 及 BT 是共用一組天線,所以在硬體設計上更為簡便。而 BW16 為 基於 RTL8720DN 所設計的 SOC 模組,將常用的引腳連接出來, 並使用 PCB 天線。使開發輕鬆。

小結

內核組成 KM4 Arm Cortex-M4 core @ 200 MHz 及  KM0 Arm Cortex-M0 core @ 20 MHz

 WiFi 2.4G 及 WiFi 5G 協定  802.11 a/b/g/n 頻寬範圍 : 2.412-2.484GHz & 5.180-5.825GHz

  • 支援 HT20/HT40 模式
  • 支援低功耗式
  • 支援 Bluetooth 5.0 LE , 頻寬範圍 :2.402GHz – 2.480GHz
  • 工作模式 : AP , Station, AP/ Client
  • WiFi 與 BT 共用一組天線
  • 1 個 ADC
  • 2 UART 介面
  • 1 個 I2C
  • 1 個 SPI
  • 4 個 PWM
  • 全部接腳都可成為 GPIO


為了更方便使用 RTL8720DN (BW16),因此我設計了 A1 PICO 開發版。

開發重點

1. 內建 USB 5V 可自複式保險絲。
因為做實驗難免會有誤接短路的問題,尤其是 USB 是直接連接電腦。雖然 USB Hub 也有相對應的保護,多層保護可以減少發生意外機率。

2. 電池連接口 JST 2.00mm 。
在很多應用是不方便連接固定電源,在應用上會更方便。若同時接入 USB 5V 會自動切換 USB 做為主要電源。

3. 因為要使用電池應用, 所以也特別挑選工作效率好的 LDO。使電池發揮最大的效能。預設電壓區間是 3.6V ~ 4.2V

4. 預裝 I2C 提升電阻,在應用於 I2C 時都需要提升電阻,有時臨時還真找不到 。現在只要將短路 pin 接上就好。

5. 支援 Auto flash 功能也是這次修改的重點, 感謝 jojoling 提供好用的程式,讓我可以搭順風車。

連接圖

RTL8720DN,BW16

UART 驅動程式

CH9102F

https://www.wch.cn/products/CH9102.html

CH9102F (本站下載點,不會更新)

Google driver dwonload.

電路圖

RTL8720DN,BW16


RTL8720DN(BW16) 加入 Arduino IDE

首先先將這個網址複製起來
https://github.com/ambiot/ambd_arduino/raw/master/Arduino_package/package_realtek_amebad_index.json

打開 Arduino IDE , 點開 File / Preferences

RTL8720DN,BW16

將網址貼上 紅框 處 , 然後點 OK 儲存

接著在 Tools / Board: / Boards Manager...

RTL8720DN,BW16

在 搜尋列直接輸入" ameba " 就會出現開發板資訊 , 在右側會有 Install 的 按鈕。 因為我的 Arduino IDE 安裝完成,所以出現不一樣字樣。 點 " Install " 開始安裝 會需要等待一些時間, 可以先去泡一杯咖啡再回來。

RTL8720DN,BW16

稍待片刻後,系統就會自動安裝完成。
在 Tools / Board: / Amaba ARM (32bit) Boards 裡, 應該會找到 RTL8720DN (BW16) 這個選項。
到這裡 安裝 RTL8720DN(BW16) 到 Arduino IDE 的部分已經做完了。

將開發板連接電腦 USB 並開啟 Arduino IDE 並選好 開發板名稱 及 COM Port 位置

RTL8720DN,BW16

溫馨提醒:

本開發板有 Auto flash 自動上傳功能, 請將 Auto Upload mode 設定為 Enable

RTL8720DN,BW16


測試 Blink 程式


int YelloLED = 9; //PA15

// the setup function runs once when you press reset or power the board
void setup() {
  // initialize digital pin LED_BUILTIN as an output.
  pinMode(YelloLED, OUTPUT);
}

// the loop function runs over and over again forever
void loop() {
  digitalWrite(YelloLED, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(1000);                       // wait for a second
  digitalWrite(YelloLED, LOW);    // turn the LED off by making the voltage LOW
  delay(1000);                       // wait for a second
}

示範影片



如何購買 A1 Pico 開發板

Buy A1 Pico Board.

開發資源

2021年8月21日星期六

[MicroPython] STM32 + MicroPython + SSD1306 基本使用

 今天來測試 SSD1306 OLED 顯示模組,SSD1306 是透過 I2C 來控制。所以在我們 DIY Pyboard 連接 VCC,GND,SCL,SDA。為了使用麵包板方便連接,我使用 PB3 (SDA) ,PB10(SCL) 這一組來使用。以這次設計的 板子架構來說是 第 2 組 I2C。


準備

STM32_MiniBoard x 1
SSD1306                 x 1
麵包板                    x 1
若干杜邦線


接線

MicroPython



開始

在 MicroPython 裡已經有 SSD1306 驅動程式,在源碼 Drivers/display 目錄裡。不過,在這我自行編譯的 MicroPython firmware 已經加入 SSD1306 驅動,所以不用另外拷貝出來使用。首先我們將 開啟 Thonny 並且開啟 REPL 提示列。

輸入以下程式段

from machine import Pin,I2C
i2c = I2C(2)
I2C(2) 是指 第二組 I2C 通訊

我們可以測試一下
i2c.scan()

如果沒有問題,會顯示以下結果。




表示 SSD1306 的位置是 60 (為10進制, 16進制為 0x3C) ,且 I2C 接線無誤。
繼續輸入以下程式段

from ssd1306 import SSD1306_I2C
oled = SSD1306_I2C(128, 64, i2c)
oled.text("hello makdev.net",0,0)
oled.show()
實際畫面是
MicroPython













我們接著試著使用 Raspberry Pi Pico  RP2040 的 範例測試一下 source code 連結 (https://github.com/raspberrypi/pico-micropython-examples/tree/master/i2c/1306oled/i2c_1306oled_using_defaults.py)

源碼的 第 9 行 



i2c = I2C(0)
改為

i2c = I2C(2)
在 Thonny 中,使用檔案開啟功能 開啟 MicroPython Device 的方式,開啟 main.py 並將全部 Sorce code 貼上並儲存。



# Display Image & text on I2C driven ssd1306 OLED display
from machine import Pin, I2C
from ssd1306 import SSD1306_I2C
import framebuf

WIDTH  = 128                                            # oled display width
HEIGHT = 32                                             # oled display height

i2c = I2C(2)                                            # Init I2C using I2C0 defaults, SCL=Pin(GP9), SDA=Pin(GP8), freq=400000
print("I2C Address      : "+hex(i2c.scan()[0]).upper()) # Display device address
print("I2C Configuration: "+str(i2c))                   # Display I2C config


oled = SSD1306_I2C(WIDTH, HEIGHT, i2c)                  # Init oled display

# Raspberry Pi logo as 32x32 bytearray
buffer = bytearray(b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00|?\x00\x01\x86@\x80\x01\x01\x80\x80\x01\x11\x88\x80\x01\x05\xa0\x80\x00\x83\xc1\x00\x00C\xe3\x00\x00~\xfc\x00\x00L'\x00\x00\x9c\x11\x00\x00\xbf\xfd\x00\x00\xe1\x87\x00\x01\xc1\x83\x80\x02A\x82@\x02A\x82@\x02\xc1\xc2@\x02\xf6>\xc0\x01\xfc=\x80\x01\x18\x18\x80\x01\x88\x10\x80\x00\x8c!\x00\x00\x87\xf1\x00\x00\x7f\xf6\x00\x008\x1c\x00\x00\x0c \x00\x00\x03\xc0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00")

# Load the raspberry pi logo into the framebuffer (the image is 32x32)
fb = framebuf.FrameBuffer(buffer, 32, 32, framebuf.MONO_HLSB)

# Clear the oled display in case it has junk on it.
oled.fill(0)

# Blit the image from the framebuffer to the oled display
oled.blit(fb, 96, 0)

# Add some text
oled.text("Raspberry Pi",5,5)
oled.text("Pico",5,15)

# Finally update the oled display so the image & text is displayed
oled.show()
點擊 Run 按鈕
MicroPython



畫面變成
MicroPython






相關文章

開始第一個 micropython 程式
STM32F4 使用 MicroPython 應用
如何安裝 PyBoard 的 Com Port


2021年8月8日星期日

[MicroPython] 開始第一個 micropython 程式

拿到 STM32F401_MiniPyboard 之後就想先測試一下 MicroPython 簡單的程式,順便驗證一下板子。開始之前 先預安裝 Thonny  IDE ,這是編輯程式 及 上傳程式的工具。它同時支援 Windows , Linux 及 MAC 系統。

安裝程式

可以在這裡下載安裝 (https://thonny.org/) , 安裝方式依序按下一步安裝即可。


執行 Thonnny IDE


Thonny


設定 Thonny IDE

先將 STM32F401_MiniPyboard 接入 USB cable。
在 Thonny IDE 的選單點開 Run ->Select interpreter...  並選擇 Interpreter Tab。

選擇 MicroPython(generic)

MicroPython


選好後 下方會出現 Port 的選擇 , 選擇剛接入開發板後 新增的 Com port。 然後點下方的 OK

MicroPython



回到主畫面後 , 在 Shell 窗口 是 REPL 互動窗口。會顯示以下

MicroPython



表示到現在已經正常連接了。
我們可以在 Shell / REPL 窗口直接編輯程式。

MicroPython

依序往下編輯, 這時候 LED 應該是會閃爍了。


如果要開發板上電之後開始執行程式?


點選單 File -> Open ...



選擇 MicroPython device




選擇 main.py 開啟,並將剛剛的 程式 填入




儲存後 ,在 Shell 按組合鍵 Ctrl + D 軟啟動。或是 重新上電

這時候 LED 應該會開始閃爍。