风筝
发表于: 2017-8-30 14:51:14 | 显示全部楼层

本文主要介绍了一款基于ATtiny85微控制器的四通道温度计,该温度计可以同时监测四个温度传感器的温度,并且实时在小型128x32 OLED液晶屏上进行显示。

thermometerdisplay.jpg


该温度计可以用于任何需要监控多个温度点的应用中,例如控制温室、检查功率放大器中的输出晶体管、监控超频游戏PC中的关键点、监控Raspberry Pi上的芯片,或者检查家里各个房间的温度。

以下示例是使用四通道温度计监视A类功率放大器功率晶体管的温度:

thermometerdisplay2.jpg


简介

这款四通道温度计采用了ATtiny85微控制器来读取四个DS18B20或MAX31820温度传感器的数据,使用1-Wire协议,并在小型OLED液晶屏上显示温度。

我选择了一个128x32 OLED显示屏,它是一个宽约2.5厘米(1寸)的小型显示屏,具有非常清晰、明亮的单色显示屏和SPI接口,可从Adafruit 或Proto-PIC购买。Aliexpress也提供了类似的显示屏。

对于传感器,我使用的是TO-92封装的DS12B20温度传感器,电源范围为3.0V至5.5V。 MAX31820也可以满足应用,而且价格便宜,但是其最大供电电压为3.7V。或者,您可以在Banggood上找到一包10个DS18B20。 DS18B20温度传感器也可以封装在防水电缆中。

您可以使用数米的双绞线连接温度传感器;使用长电缆时,建议使用线性拓扑结构,而不是星形配置。

该程序使用简单的1-Wire例程。以下是全部的电路图:

thermometerdisplay.gif

33kΩ电阻和0.1μF电容确保在首次供电时显示屏能够正常复位。


四通道温度计的使用方法

要使用四通道温度计,您首先需要设置如下:

■     连接您将要使用的DS18B20 / MAX31820温度传感器中的额一个,然后通电。

传感器的序列号将被读取并存储在ATtiny85的EEPROM中,显示屏会显示第一个显示位置的温度。

■     剩下的三个温度传感器重复进行操作,一次连接一个温度传感器,然后通电。

剩余的三个序列号将会存储在EEPROM中。

■     最后,在1-Wire总线上并联所有四个温度传感器。

显示屏将显示所有四个温度,动态更新。


请注意,如果尝试运行程序而没有连接任何传感器,显示屏将显示“?”。如果您一次连接两个或多个传感器,而没有进行“学习”步骤,显示屏将保持空白。


工作原理

所有1-Wire器件都使用ROM中唯一的48位序列号进行编程,以便识别连接到同一1-Wire总线的多个器件。

要从特定的DS18B20 / MAX31820传感器读取温度,您需要发送Match ROM命令,然后发送要访问的传感器的序列号。

要找到1-Wire总线上所有设备的序列号,您可以使用一个称为Search ROM的特殊例程,该程序一次测试48位,以产生冲突,然后构建设备序列号的树。这是一个复杂的过程;如果你想这样做,使用1-Wire库之一。幸运的是,找到序列号的方法要简单得多:您可以一次将设备连接到1-Wire总线,并使用Read ROM命令直接读取每个序列号。这是我在这个应用程序中使用的方法。

四通道温度计使用ATtiny85上的EEPROM来存储四个温度传感器的签名。要“训练”四通道温度计,您可以连接四个要使用的温度传感器之一,并施加电力。在setup()中,程序会尝试读取ROM命令,如果读回的数据有一个有效的CRC,它就知道它已经读取了一个有效的序列号,并存储在EEPROM中:

  1. void loop () {
  2.   for (int i=0; i<4; i++) {
  3.     int line = (i / 2)*2;
  4.     int col = (i % 2)*11;
  5.     // Display temperatures of all devices on bus
  6.     cli();                            // No interrupts
  7.     if (OneWireReset() != 0) {
  8.       sei();
  9.       PlotChar('?', line, col);
  10.     } else if (EepromLoad(i) == 0) {      
  11.       OneWireWrite(MatchROM);
  12.       OneWireWriteBytes(8);
  13.       OneWireWrite(ConvertT);
  14.       while (OneWireRead() != 0xFF);
  15.       OneWireReset();
  16.       OneWireWrite(MatchROM);
  17.       OneWireWriteBytes(8);
  18.       OneWireWrite(ReadScratchpad);
  19.       OneWireReadBytes(9);
  20.       sei();                          // Interrupts
  21.       if (OneWireCRC(9) == 0) {
  22.         int temp = DataBytes[1]<<8 | DataBytes[0];
  23.         PlotTemperature(temp>>4, line, col);
  24.       } else PlotChar('X', line, col);
  25.     }
  26.   }
  27. }
复制代码

最多可以学习四个传感器,然后将它们全部连接到电路。 这次Read ROM命令失败,因为总线冲突,所以程序的训练阶段被忽略。

请注意,如果由于某种原因要擦除存储在EEPROM中的序列号,例如使用不同的传感器,请在setup()开始时取消注释EepromClear()调用,并运行程序一次。


显示温度

主程序在loop()中依次从EEPROM读取每个签名,使用Match ROM命令访问适当的传感器,读取温度,并调用PlotTemperature()将其显示在显示屏上的适当位置:

  1. void loop () {
  2.   for (int i=0; i<4; i++) {
  3.     int line = (i / 2)*2;
  4.     int col = (i % 2)*11;
  5.     // Display temperatures of all devices on bus
  6.     cli();                            // No interrupts
  7.     if (OneWireReset() != 0) {
  8.       sei();
  9.       PlotChar('?', line, col);
  10.     } else if (EepromLoad(i) == 0) {      
  11.       OneWireWrite(MatchROM);
  12.       OneWireWriteBytes(8);
  13.       OneWireWrite(ConvertT);
  14.       while (OneWireRead() != 0xFF);
  15.       OneWireReset();
  16.       OneWireWrite(MatchROM);
  17.       OneWireWriteBytes(8);
  18.       OneWireWrite(ReadScratchpad);
  19.       OneWireReadBytes(9);
  20.       sei();                          // Interrupts
  21.       if (OneWireCRC(9) == 0) {
  22.         int temp = DataBytes[1]<<8 | DataBytes[0];
  23.         PlotTemperature(temp>>4, line, col);
  24.       } else PlotChar('X', line, col);
  25.     }
  26.   }
  27. }
复制代码

如果在读取其中一个温度时发生CRC错误,程序在该位置显示“X”。 这通常意味着您断开了该传感器。

cli()和sei()调用禁用1-Wire例程周围的中断; 它们是可选的,但没有它们,由于Arduino millis()中断,温度读数偶尔会给出CRC错误。

温度通过例程PlotTemperature()写入显示器,调用PlotChar()来绘制从-99°C到999°C的字符宽度为五个字符的温度的各个字符。 这涵盖DS18B20支持的范围,-55°C至125°C:

  1. void PlotTemperature (int temp, int line, int column) {
  2.   boolean dig = false;
  3.   unsigned int j = 100;
  4.   if (temp < 0) {
  5.     PlotChar('-', line, column);
  6.     temp = - temp;
  7.     column = column + Scale;
  8.     j = 10;
  9.   }
  10.   for (int d=j; d>0; d=d/10) {
  11.     char c = DigitChar(temp, d);
  12.     if (c == '0' && !dig) c = ' '; else dig = true;
  13.     PlotChar(c, line, column);
  14.     column = column + Scale;
  15.   }
  16.   PlotChar('`', line, column); column = column + Scale;
  17.   PlotChar('C', line, column);
  18. }
复制代码


绘制字符

为了避免需要一个内存缓冲区,大约需要512字节或RAM,超出ATtiny85提供的资源,字符直接从字符定义绘制到显示器。

为了灵活性,PlotChar()例程提供了在6x8像素字符单元格上显示正常大小的字符或占用12x16像素的双倍大小的字符的选项。 您可以使用双重字符在显示屏上以°C的四种温度调节,这使得显示器更易读。 如果要显示更多的通道,或十分之一度的精度,可以使用正常大小的字符,或者混合使用两者。 字符大小由全局变量Scale控制:

  1. oid PlotChar(char c, int line, int column) {
  2.   PINB = 1<<cs; // cs low
  3.   // Set column address range
  4.   Command(0x21); Command(column*6); Command(column*6 + Scale*6 - 1);
  5.   // Set page address range
  6.   Command(0x22); Command(line); Command(line + Scale - 1);
  7.   for (uint8_t col = 0 ; col < 6; col++) {
  8.     int bits = pgm_read_byte(&CharMap[c-32][col]);
  9.     if (Scale == 1) Data(bits);
  10.     else {
  11.       bits = Stretch(bits);
  12.       for (int i=2; i--;) { Data(bits); Data(bits>>8); }
  13.     }
  14.   }
  15.   PINB = 1<<cs; // cs high
  16. }
复制代码

参数行和列用正常大小的字符指定屏幕上绘制字符的位置;所以行可以在0和5之间,列可以在0和20之间,其中(0,0)对应于左上角的字符位置。

图形显示是基于我早期的项目Tiny Terminal,修改为128x32显示,显示双字符字符的技术来自我的项目Big Text for Little Display。


编译程序

我使用Spence Konde的ATTiny Core编译了该程序,该内核取代了早期的ATtiny内核。在Boards菜单的ATtiny Universal标题下选择ATtiny x5 series选项。然后在后续菜单中选择Timer 1 Clock: CPU, B.O.D. Disabled, ATtiny85, 8 MHz (internal)。选择 Burn Bootloader正确设置保险丝。然后使用ISP(系统内编程)上传程序;我使用的是Sparkfun的Tiny AVR Programmer Board。


更多建议

1-Wire的优势在于,通过菊花链的方式可以轻松添加更多器件到1-Wire总线。当然您可以添加更多DS18B20或MAX31820温度传感器,以满足更多的测量需求。您可以使用DS2417添加时间显示,DS2417是1-Wire晶体控制的实时时钟。您可以使用1-Wire非易失性存储器芯片添加用于数据记录的非易失性存储器,例如提供20kb非易失性存储器的DS28EC20。您也可以添加一个1-Wire开关,例如DS2413或DS2408,以控制外部设备,尽管使用具有更多输出的ATtiny芯片(如ATtiny84)可能更有意义。

跳转到指定楼层
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

主题 32 | 回复: 41



手机版|

GMT+8, 2024-11-21 23:56 , Processed in 0.046770 second(s), 9 queries , Gzip On, MemCache On. Powered by Discuz! X3.5

YiBoard一板网 © 2015-2022 地址:河北省石家庄市长安区高营大街 ( 冀ICP备18020117号 )

快速回复 返回顶部 返回列表