作者rrr518 (廢文族の理沙)
看板ASM
標題Re: [問題] 74CH595 搭配 DS18B20水溫感測器的問題
時間Thu Jun 7 13:51:48 2018
自問自答一下好了
我現在用的方法是 DS18B20 在它本身更新到3.8版本之後
本身內建的延遲讀取時間
因為 request這個動作本身會用到0.75秒(我自己實測是0.779秒)
所以他們用
if (millis() - lastTempRequest >= delayInMillis) {
sensors.requestTemperatures();
resolution++;
if (resolution > 12 )
resolution = 9;
sensors.setResolution(tempDeviceAddress, resolution);
sensors.requestTemperatures();
delayInMillis = 779 / (1 << (12 - resolution));
lastTempRequest = millis();
}
這個方法來讓讀取時間分散(?
讀取的效果好很多
只是因為74CH595的關係它會一直閃
不影響閱讀數值但是看久了不太舒服
所以我還有加上thread來讓它頻率不那麼高
給有一樣問題的參考看看
當然我還是覺得有很多改進的空間!! XDDDDD
想到怎麼更進一步的板友希望可以跟我說 >///<
※ 引述《rrr518 (廢文族の理沙)》之銘言:
: 我買的LED數字顯示是用兩片74CH595
: 總共可以顯示4個數字
: http://i.imgur.com/xp5mHZk.jpg
: http://i.imgur.com/QHgEZzB.jpg
: 爬了一下文發現是用視覺暫留的方法輪流顯示數字
: 現在我要搭配DS18B20水溫感測器
: 我發現幾個問題
: 1. 取DS18B20感測器溫度時用的sensors.requestTemperatures();
: 似乎會讓程式停頓一下
: 變成前面三位數字很快閃過
: 只剩下最後一個數字一直亮著
: 2. 前三個數字變得暗暗的
: 最後一個數字很明亮
: http://i.imgur.com/SmBddP1.jpg
: 想知道是我哪邊寫不對嗎?
: 能不能改善這兩個情況
: 謝謝
: 程式碼:
: #include <OneWire.h>
: #include <DallasTemperature.h>
: #define ONE_WIRE_BUS 3
: OneWire oneWire(ONE_WIRE_BUS);
: DallasTemperature sensors(&oneWire);
: const byte dataPin = 7; // 74HC595 序列腳接「數位 7」 //DIO
: const byte latchPin = 6; // 74HC595 暫存器時脈腳接「數位 6」//RCK
: const byte clockPin = 5; // 74HC595 序列時脈腳接「數位 5」//SCK
: int index = 0; // 七段顯示器的數字索引
: int temp;
: int first = 0;
: int second = 0;
: int third = 0;
: int fourth = 0;
: const byte LED[10] = { // 記錄0~9的七段數字
: B00111111,
: B00000110,
: B01011011,
: B01001111,
: B01100110,
: B01101101,
: B01111101,
: B00100111,
: B01111111,
: B01101111,
: };
: const byte LED_P[10] = { // 記錄0~9的七段數字
: B10111111,
: B10000110,
: B11011011,
: B11001111,
: B11100110,
: B11101101,
: B11111101,
: B10100111,
: B11111111,
: B11101111,
: };
: void setup() {
: // put your setup code here, to run once:
: Serial.begin(115200);
: Serial.println("Temperature Sensor");
: // 初始化
: sensors.begin();
: pinMode(latchPin, OUTPUT);
: pinMode(clockPin, OUTPUT);
: pinMode(dataPin, OUTPUT);
: }
: void loop() {
: sensors.requestTemperatures();
: temp = sensors.getTempCByIndex(0) * 100;
: fourth = temp % 10;
: temp = temp / 10;
: third = temp % 10;
: temp = temp / 10;
: second = temp % 10;
: temp = temp / 10;
: first = temp % 10;
: digitalWrite(latchPin, LOW);
: shiftOut(dataPin, clockPin, MSBFIRST, LED[first]);
: shiftOut(dataPin, clockPin, MSBFIRST, 0xFE);
: digitalWrite(latchPin, HIGH);
: digitalWrite(latchPin, LOW);
: shiftOut(dataPin, clockPin, MSBFIRST, LED_P[second]);
: shiftOut(dataPin, clockPin, MSBFIRST, 0xFD);
: digitalWrite(latchPin, HIGH);
: digitalWrite(latchPin, LOW);
: shiftOut(dataPin, clockPin, MSBFIRST, LED[third]);
: shiftOut(dataPin, clockPin, MSBFIRST, 0xFB);
: digitalWrite(latchPin, HIGH);
: digitalWrite(latchPin, LOW);
: shiftOut(dataPin, clockPin, MSBFIRST, LED[fourth]);
: shiftOut(dataPin, clockPin, MSBFIRST, 0xF7);
: digitalWrite(latchPin, HIGH);
: }
--
※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 140.121.71.185
※ 文章網址: https://webptt.com/m.aspx?n=bbs/ASM/M.1528350710.A.DB6.html
1F:→ cs8425: 實在不懂你為啥用會用到thread? MCU不跑RTOS用不到啊 06/08 17:39
2F:→ cs8425: 會閃代表你更新頻率不夠高 或是有jitter造成更新不夠即時 06/08 17:39
3F:→ rrr518: 因為讀取時間會卡到的關係呀 06/09 01:35
4F:推 art1: 看不出設定溫度解析度跟讀取時間有什麼關係 06/09 15:19
5F:推 art1: 從這裡的程式碼可以看出讀取溫度用不到 0.75 秒 06/09 15:50
這是這支sensor他讀取的動作就是需要0.75秒
所以他們更新後才會有新的分散讀取時間的動作
補充一下
光看程式碼我也不覺得讀取時間會用到0.75秒
但是實際執行後
sensors.requestTemperatures();
這行程式碼就是會用到超過0.75秒 我個人是0.779秒
這個是sensor的問題
換成其他的sensor不太會有這個問題
這個要自己買了這支sensor來玩才會發現
網路上也有其他人有這個問題
不是只有我唷
6F:→ art1: 因為呼叫了兩次讀取溫度的函式,1.5秒的時間都無法更新七段 06/09 15:51
7F:→ art1: 顯示器,根本就不可能達成輪流顯示的效果 06/09 15:51
8F:推 art1: 應該說不可能達成視覺暫留的效果 06/09 15:55
9F:→ art1: 這段程式碼是在不斷重新設定讀取的解析度,同時延遲時間會跟 06/09 15:57
10F:→ art1: 著解析度的不同而有所變化 06/09 15:58
11F:→ art1: 就因為多了這段延遲時間,所以七段顯示器才會很閃 06/09 15:59
12F:→ art1: 因為導致更新頻率不夠多,視覺暫留的效果就變差了 06/09 15:59
是的
13F:→ cs8425: 樓上 他code只貼一半 關鍵的setWaitForConversion(false) 06/09 16:37
14F:→ cs8425: 沒貼到 我也是翻過函式庫才知道 06/09 16:37
15F:→ cs8425: requestTemperatures()跟getTempCByIndex()大概也放錯位置 06/09 16:39
16F:→ cs8425: 不懂thread原理亂用又不附上完整code 這個我實在無法幫 06/09 16:41
完整程式碼在這裡
#include <OneWire.h>
#include <DallasTemperature.h>
#include <Timer.h>
#include <Thread.h>
#include <ThreadController.h>
#define ONE_WIRE_BUS 3
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
DeviceAddress tempDeviceAddress;
const byte dataPin = 7; // 74HC595 序列腳接「數位 7」 //DIO
const byte latchPin = 6; // 74HC595 暫存器時脈腳接「數位 6」//RCK
const byte clockPin = 5; // 74HC595 序列時脈腳接「數位 5」//SCK
int index = 0; // 七段顯示器的數字索引
int temp;
int first = 0;
int second = 0;
int third = 0;
int fourth = 0;
int resolution = 12;
unsigned long lastTempRequest = 0;
int delayInMillis = 0;
Thread myThread = Thread();
const byte LED[10] = { // 記錄0~9的七段數字
B00111111,
B00000110,
B01011011,
B01001111,
B01100110,
B01101101,
B01111101,
B00100111,
B01111111,
B01101111,
};
const byte LED_P[10] = { // 記錄0~9的七段數字
B10111111,
B10000110,
B11011011,
B11001111,
B11100110,
B11101101,
B11111101,
B10100111,
B11111111,
B11101111,
};
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
//Serial.println("Temperature Sensor");
// 初始化
sensors.begin();
pinMode(latchPin, OUTPUT);
pinMode(clockPin, OUTPUT);
pinMode(dataPin, OUTPUT);
myThread.onRun(getTemp);
myThread.setInterval(2500);
sensors.getAddress(tempDeviceAddress, 0);
sensors.setResolution(tempDeviceAddress, resolution);
sensors.setWaitForConversion(false);
sensors.requestTemperatures();
delayInMillis = 779 / (1 << (12 - resolution));
lastTempRequest = millis();
temp = sensors.getTempCByIndex(0) * 100;
fourth = temp % 10;
temp = temp / 10;
third = temp % 10;
temp = temp / 10;
second = temp % 10;
temp = temp / 10;
first = temp % 10;
}
void loop() {
if(myThread.shouldRun())
myThread.run();
digitalWrite(latchPin, LOW);
shiftOut(dataPin, clockPin, MSBFIRST, LED[fourth]);
shiftOut(dataPin, clockPin, MSBFIRST, 0xF7);
digitalWrite(latchPin, HIGH);
digitalWrite(latchPin, LOW);
shiftOut(dataPin, clockPin, MSBFIRST, LED[third]);
shiftOut(dataPin, clockPin, MSBFIRST, 0xFB);
digitalWrite(latchPin, HIGH);
digitalWrite(latchPin, LOW);
shiftOut(dataPin, clockPin, MSBFIRST, LED_P[second]);
shiftOut(dataPin, clockPin, MSBFIRST, 0xFD);
digitalWrite(latchPin, HIGH);
digitalWrite(latchPin, LOW);
shiftOut(dataPin, clockPin, MSBFIRST, LED[first]);
shiftOut(dataPin, clockPin, MSBFIRST, 0xFE);
digitalWrite(latchPin, HIGH);
}
void getTemp(){
if (millis() - lastTempRequest >= delayInMillis) {
sensors.requestTemperatures();
temp = sensors.getTempCByIndex(0) * 100;
fourth = temp % 10;
temp = temp / 10;
third = temp % 10;
temp = temp / 10;
second = temp % 10;
temp = temp / 10;
first = temp % 10;
resolution++;
if (resolution > 12 )
resolution = 9;
sensors.setResolution(tempDeviceAddress, resolution);
sensors.requestTemperatures();
delayInMillis = 779 / (1 << (12 - resolution));
lastTempRequest = millis();
}
}
17F:推 disap: 另一種方法是到request裡去看他到底在搞什麼 收幾個位元資 06/17 10:33
18F:→ disap: 料要花那麼久是不可能的 多半只是用迴圈詢問sensor上某個旗 06/17 10:33
19F:→ disap: 標 把那些api找出來 放到你自己的迴圈去實現就可以 06/17 10:33
好的 我試試看~
謝謝~~
20F:推 art1: 其實0.75秒應該是等待感應器回傳資料的時間 06/17 11:04
21F:→ art1: 而不同的精度需要的時間不一樣,才有他貼的那一段延遲函式 06/17 11:04
22F:→ art1: 最簡單的作法是把延遲時間的部分換成 for 迴圈,裡面跑顯示 06/17 11:07
23F:→ art1: 資料的程式碼,這樣在等待的同時也能保持視覺暫留效果 06/17 11:07
感謝 >//<
※ 編輯: rrr518 (140.121.71.185), 06/18/2018 17:49:16