D19TCI 发表于 2017-5-22 10:17:35

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 );
}

D19TCI 发表于 2017-5-22 10:24:24

上面是一个测试用的试验品,下一步在利用剩余的A6、A0、A1、A2、A3再增加几个温度测量,同时把压力的测量也做进去,找个盒子装了,放在车上坐行车数据记录仪。

D19TCI 发表于 2017-5-22 10:32:04

在使用LGT0.0.10最新库时,以前安装过arduino-IDE在用最新的SPI时可能会出错,解决方案见弘老大的
http://www.geek-workshop.com/thread-28834-1-1.html 帖子

D19TCI 发表于 2017-5-22 10:38:16

本例还用了EEPROM,每上电一次文件自动生成一个新文件,file1.txt、file2.txt、file3.txt .........

弘毅 发表于 2017-5-22 13:37:45

屏幕好大~~~

D19TCI 发表于 2017-5-22 15:14:08

弘毅 发表于 2017-5-22 13:37
屏幕好大~~~

用了一片2004的屏,1602屏的代码就能用,只是多了两行。

D19TCI 发表于 2017-5-22 15:47:00

找到一个大气压力传感器,把大气压加入

D19TCI 发表于 2017-5-22 15:47:46

昆明今天中午的温度及气压

Damn_intuition 发表于 2017-6-1 20:40:58

:):):)
不错不错!

工作时候8F328自身发热如何?

D19TCI 发表于 2017-6-1 23:43:34

Damn_intuition 发表于 2017-6-1 20:40
不错不错!

工作时候8F328自身发热如何?

基本上不发热,LGT8F328P的12位ADC在普通的工程应用上基本能满足要求,在此基础上我已完善。我是搞发动机开发的,有时要记录发动机在整车上的运行数据。比如说,不同用户的驾驶习惯、城市道路的排温特性等。以往要用专用的车载数据记录仪设备(小日本生产的),价格太高,不能大量采用。现在我用328P加上一些通用模块,做了一个简易的车载数据记录仪,可以记录2个温度(0~800度),一个车速、一个发动机转速、油门踏板信号。采样频率设为2Hz,用一块2004屏实时显示,用SD卡存储数据。工作很稳定,装在车上,车辆上电行驶后就开始自动记录,通常可以一周提取一次数据进行分析。

Damn_intuition 发表于 2017-6-2 10:48:16

D19TCI 发表于 2017-6-1 23:43
基本上不发热,LGT8F328P的12位ADC在普通的工程应用上基本能满足要求,在此基础上我已完善。我是搞发动机 ...

听起来很赞,做好以后发群里看看。

Damn_intuition 发表于 2017-6-2 10:49:25

工业用和diy差距很大,你的这个应该遇到过很多问题吧,期望看到这些抗干扰和增稳的内容。

D19TCI 发表于 2017-6-2 17:43:40

本帖最后由 D19TCI 于 2017-6-3 10:02 编辑

Damn_intuition 发表于 2017-6-2 10:49
工业用和diy差距很大,你的这个应该遇到过很多问题吧,期望看到这些抗干扰和增稳的内容。

是的,工业用对精度、抗干扰(电磁兼容性、温度、振动等)、稳定性有相当的要求。以前用MEGA328时仅仅用来学习一下,因为10位ADC基本上精度不够,LGT的328的ADC是12位的,基本能用,所以尝试着做一些东西。
我是做产品开发的,理解作为一个产品特别是工业产品的要求,因此在不断的完善。第一步实现功能,第二步解决抗干扰、稳定性、可靠性、成本等问题,当然有软件层面也有硬件层面,比如说在测发动机转速,其实就是测频率,参考了大家的一些成果,基本上能实现,下一步就是解决上述问题,硬件方面用一片74HC14进行整形,限幅电路也是必须的(万一输了信号电压过高,可能就把芯片烧了)软件方面必要的自诊断及监控代码是必须,同时针对特性的传感器信号必要的修正也是必须的。现在在不断的测试完善。

太行摄狼 发表于 2017-8-28 19:31:54

很惭愧啊,我这搞仪表的也都没搞出楼主的东西,能吧SD程序发出来吗,学习一下

D19TCI 发表于 2017-9-14 11:14:05

太行摄狼 发表于 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
查看完整版本: OCROBOT 8F328P 制作的温度测量、记录仪(用最新SPI)