两位数温度计



作者用这个两位数的LED温度计作为生日礼物送给朋友的儿子。 他只有两岁,已经在阅读数字,但字母却不在。 现在,他可以自己找出窗外的温度。 温度计中的传感器是根据1-Wire协议运行的DS18B20芯片,而微控制器是ATtiny84类型的。 棋盘是正方形的,侧面为25毫米,大小相当于50便士的硬币。 作者计划将板子放在防水盒中,然后放在窗户外面。 指示灯每24秒短暂亮起一次,CR2032电池可持续使用大约一年。
温度计的工作温度范围是-19至+99°C。 如有必要,减号和减号同时以高顺序显示。 超出范围时,将显示字母Lo或Hi。 您可以通过使用带点为负的线段来“教导”设备显示低于-19°C的温度。

根据此方案,该设备先前已组装在面包板上:



涉及微控制器的所有输出,使用内置的8 MHz时钟发生器。 原型如下:



原型使用TO-92封装的DS18B20,PDIP封装的ATtiny84和3.6英寸的3621AS指示器。 然后作者在Eagle中开发了该板,并在PCBway中订购了它。 这里的微控制器已经在SOIC情况下,传感器在µSOP情况下,电阻,电容器和显示器的尺寸为0805。除显示器外的所有部件均由Youyue 858D +吹风机在250°C的温度下焊接。

原型和印刷电路板都具有带有公共阳极的指示器。 该设备有两种版本,带有红色和黄色指示器。 红色-在KDPV上,黄色-在这里:



背面焊接20毫米锂电池的支架(名称以20开头的任何一个,即2016、2025或2032):



写入固件后,微控制器大部分时间处于睡眠模式,并在看门狗定时器中断后唤醒。 在实现1-Wire接口时,涉及同一作者的工作时间 。 以1 MHz的频率运行的微控制器的16位计时器非常耗时:

void OneWireSetup () { TCCR1A = 0<<WGM10; // Normal mode TCCR1B = 0<<WGM12 | 2<<CS10; // Normal mode, divide clock by 8 } 

基于OCR0A输出比较寄存器,DelayMicros()子例程提供指定的微秒延迟:

 void DelayMicros (unsigned int micro) { TCNT1 = 0; TIFR1 = 1<<OCF1A; OCR1A = micro; while ((TIFR1 & 1<<OCF1A) == 0); } 

DisplayTemperature()例程从传感器读取温度值并显示。 由于总线上只有一个传感器,因此您可以忽略序列号,而只给出“跳过ROM”命令,然后将以下所有命令发送到任何设备:

 void DisplayTemperature () { cli(); // No interrupts if (OneWireReset() != 0) { sei(); DisplayError(0); // Device not found } else { OneWireWrite(SkipROM); OneWireWrite(ConvertT); while (OneWireRead() != 0xFF); OneWireReset(); OneWireWrite(SkipROM); OneWireWrite(ReadScratchpad); OneWireReadBytes(9); sei(); // Interrupts if (OneWireCRC(9) == 0) { int temp = DataWords[0]; Display((temp+8)>>4); // Round to nearest degree } else DisplayError(1); // CRC error } } 

响应该请求,传感器以16位有符号整数的形式返回温度值,单位为1/16度。 该数字将四舍五入到最接近的整数度,并通过调用Display()例程进行显示。

DisplayError()子例程显示微控制器与1-Wire总线上的传感器交互时的错误:

 void DisplayError (int no) { Buffer[0] = Error; Buffer[1] = no; } 

E0-未检测到传感器,E1-CRC错误。

用于动态指示的数据取自Buffer []数组。 例如,要显示数字20,您必须执行以下操作:

 Buffer[0]=2; Buffer[1]=0; 

计时器计数器0产生频率为125 Hz的中断,足以消除闪烁。 首先,在setup()中配置计时器

 TCCR0A = 2<<WGM00; // CTC mode; count up to OCR0A TCCR0B = 0<<WGM02 | 4<<CS00; // Divide by 256 OCR0A = 250-1; // Compare match at 125Hz TIMSK0 = 0; // Interrupts initially off 

比较期间匹配的中断处理例程将调用DisplayNextDigit()例程,然后以相反的方向进行计数:

 ISR(TIM0_COMPA_vect) { DisplayNextDigit(); Ticks--; } 

DisplayNextDigit()子例程从Buffer []数组中的相应单元读取数据,并在相应的显示位中包含所需的段。 该程序使用#define在具有公共阴极或阳极的指示器之间进行选择。 如果加电后所有段均立即点亮,则显示类型与固件中指定的类型不匹配。 对于公共阴极,子例程必须替换为以下内容:

 void DisplayNextDigit () { PORTB = PORTB | 1<<digit; // Turn old digit off digit = digit ^ 1; // Toggle between 0 and 1 char segs = charArray[Buffer[digit]]; PORTA = segs; // Lit segments high PORTB = PORTB & ~(1<<digit); // Turn new digit on } 

最后,Display()例程产生一个两位数以写入Buffer []数组:

 void Display (int n) { int units = n % 10; int tens = n / 10; int temp0 = tens; int temp1 = abs(units); if (tens < -1) {temp0 = Lo; temp1 = Lo+1; } else if (tens > 9) {temp0 = Hi; temp1 = Hi+1; } else if (tens == -1) temp0 = Minus1; else if ((tens == 0) && (units >= 0)) temp0 = Blank; else if ((tens == 0) && (units < 0)) temp0 = Minus; Buffer[0] = temp0; Buffer[1] = temp1; } 

它还考虑了将负号与高单位显示一起显示的情况,以及有关温度超出范围的消息。

为了最大程度地节能,禁用了ADC,USI和ADC时钟发生器,并启用了PWR_DOWN睡眠模式:

  ADCSRA &= ~(1<<ADEN); // Disable ADC to save power PRR = 1<<PRUSI | 1<<PRADC; // Turn off clocks to USI & ADC to save power set_sleep_mode(SLEEP_MODE_PWR_DOWN); 

主程序显示温度达十分之一秒,然后打开睡眠模式。 原来,这是最短的显示时间,方便阅读。 温度显示前两秒钟,该点短暂闪烁:

 void loop () { Buffer[0] = DP; Buffer[1] = Blank; DisplayOn(12); WDDelay(6); // Sleep for 1 second Buffer[0] = Blank; Buffer[1] = DP; DisplayOn(12); WDDelay(6); // Sleep for 1 second DisplayTemperature(); DisplayOn(12); WDDelay(9); // Sleep for 8 seconds WDDelay(9); // Sleep for 16 seconds WDDelay(9); // Sleep for 24 seconds } 

由于三个看门狗呼叫,每个持续8秒,因此显示屏保持关闭状态24秒钟。 指示器运行时,电流消耗为6.6 mA,在睡眠模式下为4.7μA,平均电流消耗为1/240 * 6.6 mA。 CR2032电池的典型容量为225 mAh,因此足以用于(225 / 6.6)x 240/24 = 340天-不到一年。

组件的温度范围如下:微控制器和指示器--40至+ 85°C,电阻器和电容器--55至+125°C,电池--20至+70°C。 扩展温度范围BR2032的元件将在-30至+85°C的温度范围内工作。

该Spence Konde开发使该微控制器与Arduino兼容。 在IDE中,在Board菜单的ATTinyCore部分中选择ATtiny24 / 44/84。 然后,您需要设置以下选项,而不关注其余部分:

 Chip: "ATtiny84" Clock: "8 MHz (internal)" BOD: "BOD Disabled" Pin Mapping: "Clockwise (like damellis core)" 

该程序使用Pomona测试夹上传,并置于微控制器顶部并连接至SparkFun Tiny AVR编程器。 首先,您需要选择Burn Bootloader,然后选择Upload。

链接:该程序的全文董事会和GitHub上的程序 ,以及OSHpark 董事会

Source: https://habr.com/ru/post/zh-CN454220/


All Articles