作者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/cn.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