OCROBOT 8F328P 制作的温度测量、记录仪(用最新SPI)
本帖最后由 D19TCI 于 2017-9-14 11:12 编辑昨天弘老大更新了LGT的最新SPI库,解决了SD的问题,现用12位的ADC、K分度的热电偶变送器测量温度、DS1302时钟模块、2004液晶显示屏、SD卡模块做了一个温度的测量及记录仪。
实际效果图:
存储的文件file20.txt
存储文件的内容
有弘老大的软硬件支持,让单片机应用简单化,我们只用集中精力解决应用问题,编程稍加学习就能用。再次感谢弘老大。
把程序贴上,比较乱,供参考
/*
用K分度热电偶作为传感器;
用4~20ma的变送器处理信号;
通过143欧电阻转换成电压信号后送入MCU的A0端口;
用2004液晶显示屏显示所测量的温度值。
*/
/* 2004液晶显示屏管脚定义
GND -> OCROBOT_LGT8F328P GND
VCC -> OCROBOT_LGT8F328P 5V
SDA -> OCROBOT_LGT8F328P A4
SCL -> OCROBOT_LGT8F328P A5
*/
/* DS1302管脚定义
GND -> OCROBOT_LGT8F328P GND
VCC -> OCROBOT_LGT8F328P 5V
RST(DS1302 pin5) -> Arduino D5
DAT(DS1302 pin6) -> Arduino D6
CLK(DS1302 pin7) -> Arduino D7
*/
/* SD卡管脚定义
GND -> OCROBOT_LGT8F328P GND
VCC 5v-> OCROBOT_LGT8F328P 5V
CS -> OCROBOT_LGT8F328P D4
MOSI -> OCROBOT_LGT8F328P MOSI(D11)
SCK -> OCROBOT_LGT8F328PSCK (D13)
MISO -> OCROBOT_LGT8F328P MISO(D12)
*/
#include <EEPROM.h>
#include <stdio.h>
#include <string.h>
#include <DS1302.h>
#include <SPI.h>//SD
#include <SD.h> //SD
#include <LiquidCrystal_I2C.h>
#include <Wire.h>
LiquidCrystal_I2C lcd(0x3F, 20, 4); // set the LCD address to 0x3F for a 20 chars and 4
int potpin = 0 ; //定义温度信号输入的模拟接口
int a;
char buf;//日期变量缓存
char day;
char tim;
char AA;
char CC = "file";
char BB = ".txt";
uint8_t CE_PIN = 5;///* DS1302接口定义
uint8_t IO_PIN = 6;
uint8_t SCLK_PIN = 7;
/* 创建 DS1302 对象 */
DS1302 rtc(CE_PIN, IO_PIN, SCLK_PIN);
File myFile;//SD存储的文件名
float T1 ;
int n ;
int n1 ;
int temperature ;//定义温度值变量
float voltage ;
void setup()
{
analogReference (INTERNAL2V048); //定义ADC的基准参考电压为内部2.048V;
// EEPROM.write(1,0); //文件名序号复位到file1.txt
a = EEPROM.read(1); //读取上一次文件名序号
a = a + 1;
EEPROM.write(1, a); //当前文件名序号写入EEPROM
snprintf(AA, sizeof(AA), "%s%0d%s", CC, a, BB );//生成文件名字符串
rtc.write_protect(false);
rtc.halt(false);
lcd.init(); // initialize the lcd
lcd.backlight();
if (!SD.begin(4))
{
lcd.setCursor(0, 2);
lcd.print("SD card failed!");
lcd.setCursor(0, 3);
lcd.print("file not save:");
delay(2000);
return;
}
lcd.setCursor(0, 2);
lcd.print("SD card OK!");
lcd.setCursor(0, 3);
lcd.print("file save:");
lcd.print(AA);
}
void loop()
{
// lcd.setCursor(0, 0);
//lcd.print(AA);
myFile = SD.open(AA, FILE_WRITE);//SD
for (n1 = 1 ; n1 < 50 ; n1++)
{
T1 = 0;
print_time();
for (n = 1 ; n < 21 ; n++)
{
voltage = analogRead(potpin);//读取模拟接口0 的值,并将其赋给T1
delay(50);
T1 = T1 + voltage;
}
T1 = T1 / 20 ;
voltage = 0.5 * T1 ;//2.048内部参考时的换算公式加修正
temperature = map(voltage, 595.0, 2900.0, -50, 650) ; //4~20ma的电流信号通过143欧姆电阻取样后,送入A7计算后得出当前温度值。
lcd.setCursor(0, 1);
lcd.print("Temperature: "); //起到清屏的作用,无明显闪烁现象。
lcd.setCursor(0, 1);
lcd.print("Temperature: ");
lcd.print(temperature);
lcd.print(" C");
lcd.setCursor(0, 0);
lcd.print(buf);
myFile.print(buf), myFile.print("Temperature="), myFile.print(temperature) , myFile.println("C");
}
myFile.close();
//lcd.clear(); //清屏,用此功能LED屏有闪烁现象
}
void print_time()
{
/* 从 DS1302 获取当前时间 */
Time t = rtc.time();
/* 将星期从数字转换为名称 */
memset(day, 0, sizeof(day));
switch (t.day)
{
case 1: strcpy(day, "Sunday"); break;
case 2: strcpy(day, "Monday"); break;
case 3: strcpy(day, "Tuesday"); break;
case 4: strcpy(day, "Wednesday"); break;
case 5: strcpy(day, "Thursday"); break;
case 6: strcpy(day, "Friday"); break;
case 7: strcpy(day, "Saturday"); break;
}
/* 将日期代码格式化凑成buf等待输出 */
snprintf(buf, sizeof(buf), "%04d-%02d-%02d %02d:%02d:%02d ", t.yr, t.mon, t.date, t.hr, t.min, t.sec );
snprintf(CC, sizeof(CC), "%02d%02d", t.mon, t.date );
}
上面是一个测试用的试验品,下一步在利用剩余的A6、A0、A1、A2、A3再增加几个温度测量,同时把压力的测量也做进去,找个盒子装了,放在车上坐行车数据记录仪。 在使用LGT0.0.10最新库时,以前安装过arduino-IDE在用最新的SPI时可能会出错,解决方案见弘老大的
http://www.geek-workshop.com/thread-28834-1-1.html 帖子 本例还用了EEPROM,每上电一次文件自动生成一个新文件,file1.txt、file2.txt、file3.txt .........
屏幕好大~~~ 弘毅 发表于 2017-5-22 13:37
屏幕好大~~~
用了一片2004的屏,1602屏的代码就能用,只是多了两行。 找到一个大气压力传感器,把大气压加入
昆明今天中午的温度及气压 :):):)
不错不错!
工作时候8F328自身发热如何? Damn_intuition 发表于 2017-6-1 20:40
不错不错!
工作时候8F328自身发热如何?
基本上不发热,LGT8F328P的12位ADC在普通的工程应用上基本能满足要求,在此基础上我已完善。我是搞发动机开发的,有时要记录发动机在整车上的运行数据。比如说,不同用户的驾驶习惯、城市道路的排温特性等。以往要用专用的车载数据记录仪设备(小日本生产的),价格太高,不能大量采用。现在我用328P加上一些通用模块,做了一个简易的车载数据记录仪,可以记录2个温度(0~800度),一个车速、一个发动机转速、油门踏板信号。采样频率设为2Hz,用一块2004屏实时显示,用SD卡存储数据。工作很稳定,装在车上,车辆上电行驶后就开始自动记录,通常可以一周提取一次数据进行分析。 D19TCI 发表于 2017-6-1 23:43
基本上不发热,LGT8F328P的12位ADC在普通的工程应用上基本能满足要求,在此基础上我已完善。我是搞发动机 ...
听起来很赞,做好以后发群里看看。 工业用和diy差距很大,你的这个应该遇到过很多问题吧,期望看到这些抗干扰和增稳的内容。 本帖最后由 D19TCI 于 2017-6-3 10:02 编辑
Damn_intuition 发表于 2017-6-2 10:49
工业用和diy差距很大,你的这个应该遇到过很多问题吧,期望看到这些抗干扰和增稳的内容。
是的,工业用对精度、抗干扰(电磁兼容性、温度、振动等)、稳定性有相当的要求。以前用MEGA328时仅仅用来学习一下,因为10位ADC基本上精度不够,LGT的328的ADC是12位的,基本能用,所以尝试着做一些东西。
我是做产品开发的,理解作为一个产品特别是工业产品的要求,因此在不断的完善。第一步实现功能,第二步解决抗干扰、稳定性、可靠性、成本等问题,当然有软件层面也有硬件层面,比如说在测发动机转速,其实就是测频率,参考了大家的一些成果,基本上能实现,下一步就是解决上述问题,硬件方面用一片74HC14进行整形,限幅电路也是必须的(万一输了信号电压过高,可能就把芯片烧了)软件方面必要的自诊断及监控代码是必须,同时针对特性的传感器信号必要的修正也是必须的。现在在不断的测试完善。 很惭愧啊,我这搞仪表的也都没搞出楼主的东西,能吧SD程序发出来吗,学习一下 太行摄狼 发表于 2017-8-28 19:31
很惭愧啊,我这搞仪表的也都没搞出楼主的东西,能吧SD程序发出来吗,学习一下
程序未整理,比较乱,供参考,见谅好久未上论坛了
/*
用K分度热电偶作为传感器;
用4~20ma的变送器处理信号;
通过143欧电阻转换成电压信号后送入MCU的A0端口;
用2004液晶显示屏显示所测量的温度值。
*/
/* 2004液晶显示屏管脚定义
GND -> OCROBOT_LGT8F328P GND
VCC -> OCROBOT_LGT8F328P 5V
SDA -> OCROBOT_LGT8F328P A4
SCL -> OCROBOT_LGT8F328P A5
*/
/* DS1302管脚定义
GND -> OCROBOT_LGT8F328P GND
VCC -> OCROBOT_LGT8F328P 5V
RST(DS1302 pin5) -> Arduino D5
DAT(DS1302 pin6) -> Arduino D6
CLK(DS1302 pin7) -> Arduino D7
*/
/* SD卡管脚定义
GND -> OCROBOT_LGT8F328P GND
VCC 5v-> OCROBOT_LGT8F328P 5V
CS -> OCROBOT_LGT8F328P D4
MOSI -> OCROBOT_LGT8F328P MOSI(D11)
SCK -> OCROBOT_LGT8F328PSCK (D13)
MISO -> OCROBOT_LGT8F328P MISO(D12)
*/
#include <EEPROM.h>
#include <stdio.h>
#include <string.h>
#include <DS1302.h>
#include <SPI.h>//SD
#include <SD.h> //SD
#include <LiquidCrystal_I2C.h>
#include <Wire.h>
LiquidCrystal_I2C lcd(0x3F, 20, 4); // set the LCD address to 0x3F for a 20 chars and 4
int potpin = 0 ; //定义温度信号输入的模拟接口
int a;
char buf;//日期变量缓存
char day;
char tim;
char AA;
char CC = "file";
char BB = ".txt";
uint8_t CE_PIN = 5;///* DS1302接口定义
uint8_t IO_PIN = 6;
uint8_t SCLK_PIN = 7;
/* 创建 DS1302 对象 */
DS1302 rtc(CE_PIN, IO_PIN, SCLK_PIN);
File myFile;//SD存储的文件名
float T1 ;
int n ;
int n1 ;
int temperature ;//定义温度值变量
float voltage ;
void setup()
{
analogReference (INTERNAL2V048); //定义ADC的基准参考电压为内部2.048V;
// EEPROM.write(1,0); //文件名序号复位到file1.txt
a = EEPROM.read(1); //读取上一次文件名序号
a = a + 1;
EEPROM.write(1, a); //当前文件名序号写入EEPROM
snprintf(AA, sizeof(AA), "%s%0d%s", CC, a, BB );//生成文件名字符串
rtc.write_protect(false);
rtc.halt(false);
lcd.init(); // initialize the lcd
lcd.backlight();
if (!SD.begin(4))
{
lcd.setCursor(0, 2);
lcd.print("SD card failed!");
lcd.setCursor(0, 3);
lcd.print("file not save:");
delay(2000);
return;
}
lcd.setCursor(0, 2);
lcd.print("SD card OK!");
lcd.setCursor(0, 3);
lcd.print("file save:");
lcd.print(AA);
}
void loop()
{
// lcd.setCursor(0, 0);
//lcd.print(AA);
myFile = SD.open(AA, FILE_WRITE);//SD
for (n1 = 1 ; n1 < 50 ; n1++)
{
T1 = 0;
print_time();
for (n = 1 ; n < 21 ; n++)
{
voltage = analogRead(potpin);//读取模拟接口0 的值,并将其赋给T1
delay(50);
T1 = T1 + voltage;
}
T1 = T1 / 20 ;
voltage = 0.5 * T1 ;//2.048内部参考时的换算公式加修正
temperature = map(voltage, 595.0, 2900.0, -50, 650) ; //4~20ma的电流信号通过143欧姆电阻取样后,送入A7计算后得出当前温度值。
lcd.setCursor(0, 1);
lcd.print("Temperature: "); //起到清屏的作用,无明显闪烁现象。
lcd.setCursor(0, 1);
lcd.print("Temperature: ");
lcd.print(temperature);
lcd.print(" C");
lcd.setCursor(0, 0);
lcd.print(buf);
myFile.print(buf), myFile.print("Temperature="), myFile.print(temperature) , myFile.println("C");
}
myFile.close();
//lcd.clear(); //清屏,用此功能LED屏有闪烁现象
}
void print_time()
{
/* 从 DS1302 获取当前时间 */
Time t = rtc.time();
/* 将星期从数字转换为名称 */
memset(day, 0, sizeof(day));
switch (t.day)
{
case 1: strcpy(day, "Sunday"); break;
case 2: strcpy(day, "Monday"); break;
case 3: strcpy(day, "Tuesday"); break;
case 4: strcpy(day, "Wednesday"); break;
case 5: strcpy(day, "Thursday"); break;
case 6: strcpy(day, "Friday"); break;
case 7: strcpy(day, "Saturday"); break;
}
/* 将日期代码格式化凑成buf等待输出 */
snprintf(buf, sizeof(buf), "%04d-%02d-%02d %02d:%02d:%02d ", t.yr, t.mon, t.date, t.hr, t.min, t.sec );
snprintf(CC, sizeof(CC), "%02d%02d", t.mon, t.date );
}
页:
[1]
2