作业要求:焊接电路板,编译代码,并且上传到onenet平台并且显示器能够显示温度。
先展示一下最终结果:
onenet平台:
串口监视器:
实物图:
感想:首先,焊接电路板感觉挺有意思的,也比较简单。其次,代码不是自己写的,老师给了4部分然后需要自己整合。其实,我看代码的时候是一脸懵逼的,并且arduino这个软件也没接触过,什么都不了解,这个作业当时做了一整天吧,而且,疯狂的问我们班长问题,班长也给我耐心的讲解,最后的确学会了很多东西。
下面展示代码:
首先,库函数代码:
/** ============================================
* 7 segment display driver for JY-MCU module based on TM1650 chip
* Copyright (c) 2015 Anatoli Arkhipenko
*
*
* Changelog:
* v1.0.0:
* 2015-02-24 - Initial release
*
* v1.0.1:
* 2015-04-27 - Added support of program memery (PROGMEM) to store the ASCII to Segment Code table
*
* v1.0.2:
* 2015-08-08 - Added check if panel is connected during init. All calls will be disabled is panel was not connected during init.
*
* v1.1.0:
* 2015-12-20 - code clean up. Moved to a single header file. Added Gradual brightness method
*
* ===============================================*/
#include <Arduino.h>
#include <Wire.h>
#ifndef _TM1650_H_
#define _TM1650_H_
#define TM1650_USE_PROGMEM
#ifdef TM1650_USE_PROGMEM
#include <pgmspace.h>
#endif
#define TM1650_DISPLAY_BASE 0x34 // Address of the left-most digit
#define TM1650_DCTRL_BASE 0x24 // Address of the control register of the left-most digit
#define TM1650_NUM_DIGITS 16 // max number of digits
#define TM1650_MAX_STRING 128 // number of digits
#define TM1650_BIT_ONOFF 0b00000001
#define TM1650_MSK_ONOFF 0b11111110
#define TM1650_BIT_DOT 0b00000001
#define TM1650_MSK_DOT 0b11110111
#define TM1650_BRIGHT_SHIFT 4
#define TM1650_MSK_BRIGHT 0b10001111
#define TM1650_MIN_BRIGHT 0
#define TM1650_MAX_BRIGHT 7
#ifndef TM1650_USE_PROGMEM
const byte TM1650_CDigits[128] {
#else
const PROGMEM byte TM1650_CDigits[128] {
#endif
//0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0A 0x0B 0x0C 0x0D 0x0E 0x0F
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x00
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x10
0x00, 0x82, 0x21, 0x00, 0x00, 0x00, 0x00, 0x02, 0x39, 0x0F, 0x00, 0x00, 0x00, 0x40, 0x80, 0x00, // 0x20
0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7f, 0x6f, 0x00, 0x00, 0x00, 0x48, 0x00, 0x53, // 0x30
0x00, 0x77, 0x7C, 0x39, 0x5E, 0x79, 0x71, 0x6F, 0x76, 0x06, 0x1E, 0x00, 0x38, 0x00, 0x54, 0x3F, // 0x40
0x73, 0x67, 0x50, 0x6D, 0x78, 0x3E, 0x00, 0x00, 0x00, 0x6E, 0x00, 0x39, 0x00, 0x0F, 0x00, 0x08, // 0x50
0x63, 0x5F, 0x7C, 0x58, 0x5E, 0x7B, 0x71, 0x6F, 0x74, 0x02, 0x1E, 0x00, 0x06, 0x00, 0x54, 0x5C, // 0x60
0x73, 0x67, 0x50, 0x6D, 0x78, 0x1C, 0x00, 0x00, 0x00, 0x6E, 0x00, 0x39, 0x30, 0x0F, 0x00, 0x00 // 0x70
};
class TM1650 {
public:
TM1650(unsigned int aNumDigits = 4);
void init();
void clear();
void displayOn();
void displayOff();
void displayState(bool aState);
void displayString(char *aString);
int displayRunning(char *aString);
int displayRunningShift();
void setBrightness(unsigned int aValue = TM1650_MAX_BRIGHT);
void setBrightnessGradually(unsigned int aValue = TM1650_MAX_BRIGHT);
inline unsigned int getBrightness() { return iBrightness; };
void controlPosition(unsigned int aPos, byte aValue);
void setPosition(unsigned int aPos, byte aValue);
void setDot(unsigned int aPos, bool aState);
byte getPosition(unsigned int aPos) { return iBuffer[aPos]; };
inline unsigned int getNumPositions() { return iNumDigits; };
private:
char *iPosition;
bool iActive;
unsigned int iNumDigits;
unsigned int iBrightness;
char iString[TM1650_MAX_STRING+1];
byte iBuffer[TM1650_NUM_DIGITS+1];
byte iCtrl[TM1650_NUM_DIGITS];
};
// ---- Implementation ----
/** Constructor, uses default values for the parameters
* so could be called with no parameters.
* aNumDigits - number of display digits (default = 4)
*/
TM1650::TM1650(unsigned int aNumDigits) {
iNumDigits = (aNumDigits > TM1650_NUM_DIGITS) ? TM1650_NUM_DIGITS : aNumDigits;
}
/** Initialization
* initializes the driver. Turns display on, but clears all digits.
*/
void TM1650::init() {
iPosition = NULL;
for (int i=0; i<iNumDigits; i++) {
iBuffer[i] = 0;
iCtrl[i] = 0;
}
Wire.beginTransmission(TM1650_DISPLAY_BASE);
iActive = (Wire.endTransmission() == 0);
clear();
displayOn();
}
/** Set brightness of all digits equally
* aValue - brightness value with 1 being the lowest, and 7 being the brightest
*/
void TM1650::setBrightness(unsigned int aValue) {
if (!iActive) return;
iBrightness = (aValue > TM1650_MAX_BRIGHT) ? TM1650_MAX_BRIGHT : aValue;
for (int i=0; i<iNumDigits; i++) {
Wire.beginTransmission(TM1650_DCTRL_BASE+i);
iCtrl[i] = (iCtrl[i] & TM1650_MSK_BRIGHT) | ( iBrightness << TM1650_BRIGHT_SHIFT );
Wire.write((byte) iCtrl[i]);
Wire.endTransmission();
}
}
/** Set brightness of all digits equally
* aValue - brightness value with 1 being the lowest, and 7 being the brightest
*/
void TM1650::setBrightnessGradually(unsigned int aValue) {
if (!iActive || aValue == iBrightness) return;
if (aValue > TM1650_MAX_BRIGHT) aValue = TM1650_MAX_BRIGHT;
int step = (aValue < iBrightness) ? -1 : 1;
unsigned int i = iBrightness;
do {
setBrightness(i);
delay(50);
i += step;
} while (i!=aValue);
}
/** Turns display on or off according to aState
*/
void TM1650::displayState (bool aState)
{
if (aState) displayOn ();
else displayOff();
}
/** Turns the display on
*/
void TM1650::displayOn ()
// turn all digits on
{
if (!iActive) return;
for (int i=0; i<iNumDigits; i++) {
Wire.beginTransmission(TM1650_DCTRL_BASE+i);
iCtrl[i] = (iCtrl[i] & TM1650_MSK_ONOFF) | TM1650_BIT_DOT;
Wire.write((byte) iCtrl[i]);
Wire.endTransmission();
}
}
/** Turns the display off
*/
void TM1650::displayOff ()
// turn all digits off
{
if (!iActive) return;
for (int i=0; i<iNumDigits; i++) {
Wire.beginTransmission(TM1650_DCTRL_BASE+i);
iCtrl[i] = (iCtrl[i] & TM1650_MSK_ONOFF);
Wire.write((byte) iCtrl[i]);
Wire.endTransmission();
}
}
/** Directly write to the CONTROL register of the digital position
* aPos = position to set the control register for
* aValue = value to write to the position
*
* Internal control buffer is updated as well
*/
void TM1650::controlPosition(unsigned int aPos, byte aValue) {
if (!iActive) return;
if (aPos < iNumDigits) {
Wire.beginTransmission(TM1650_DCTRL_BASE + (int) aPos);
iCtrl[aPos] = aValue;
Wire.write(aValue);
Wire.endTransmission();
}
}
/** Directly write to the digit register of the digital position
* aPos = position to set the digit register for
* aValue = value to write to the position
*
* Internal position buffer is updated as well
*/
void TM1650::setPosition(unsigned int aPos, byte aValue) {
if (!iActive) return;
if (aPos < iNumDigits) {
Wire.beginTransmission(TM1650_DISPLAY_BASE + (int) aPos);
iBuffer[aPos] = aValue;
Wire.write(aValue);
Wire.endTransmission();
}
}
/** Directly set/clear a 'dot' next to a specific position
* aPos = position to set/clear the dot for
* aState = display the dot if true, clear if false
*
* Internal buffer is updated as well
*/
void TM1650::setDot(unsigned int aPos, bool aState) {
iBuffer[aPos] = iBuffer[aPos] & 0x7F |(aState ? 0b10000000 : 0);
setPosition(aPos, iBuffer[aPos]);
}
/** Clear all digits. Keep the display on.
*/
void TM1650::clear()
// clears all digits
{
if (!iActive) return;
for (int i=0; i<iNumDigits; i++) {
Wire.beginTransmission(TM1650_DISPLAY_BASE+i);
iBuffer[i] = 0;
Wire.write((byte) 0);
Wire.endTransmission();
}
}
/** Display string on the display
* aString = character array to be displayed
*
* Internal buffer is updated as well
* Only first N positions of the string are displayed if
* the string is longer than the number of digits
*/
void TM1650::displayString(char *aString)
{
if (!iActive) return;
for (int i=0; i<iNumDigits; i++) {
byte a = ((byte) aString[i]) & 0b01111111;
byte dot = ((byte) aString[i]) & 0b10000000;
#ifndef TM1650_USE_PROGMEM
iBuffer[i] = TM1650_CDigits[a];
#else
iBuffer[i] = pgm_read_byte_near(TM1650_CDigits + a);
#endif
if (a) {
Wire.beginTransmission(TM1650_DISPLAY_BASE+i);
Wire.write(iBuffer[i] | dot);
Wire.endTransmission();
}
else
break;
}
}
/** Display string on the display in a running fashion
* aString = character array to be displayed
*
* Starts with first N positions of the string.
* Subsequent characters are displayed with 1 char shift each time displayRunningShift() is called
*
* returns: number of iterations remaining to display the whole string
*/
int TM1650::displayRunning(char *aString) {
strncpy(iString, aString, TM1650_MAX_STRING+1);
iPosition = iString;
iString[TM1650_MAX_STRING] = '\0'; //just in case.
displayString(iPosition);
int l = strlen(iPosition);
if (l <= iNumDigits) return 0;
return (l - iNumDigits);
}
/** Display next segment (shifting to the left) of the string set by displayRunning()
* Starts with first N positions of the string.
* Subsequent characters are displayed with 1 char shift each time displayRunningShift is called
*
* returns: number of iterations remaining to display the whole string
*/
int TM1650::displayRunningShift() {
if (strlen(iPosition) <= iNumDigits) return 0;
displayString(++iPosition);
return (strlen(iPosition) - iNumDigits);
}
#endif /* _TM1650_H_ */
arduino代码:
#include <Wire.h>
#include <OneWire.h>
#include "TM1650.h"
#include <ESP8266WiFi.h>
#include <ESP8266mDNS.h>
#include <ESP8266HTTPClient.h>
#include <WiFiUdp.h>
#include <WiFiServer.h>
#include <WiFiClientSecure.h>
#include <WiFiClient.h>
#include <ESP8266WiFiMulti.h>
#include <cstdio>
#define BUTTON_1 0x44
#define BUTTON_2 0x45
#define BUTTON_3 0x46
#define BUTTON_4 0x47
TM1650 d;
OneWire ds(D3); //设置D3为数据线,需要上拉电阻
char line[] = "0000";
float TEMP;
byte addr[8];
byte data[12];
const char* ssid = "Call me purity";//wifi的名称
const char* password = "88888888";//wifi的密码
const char* host ="api.heclouds.com";//访问的网址
const int httpPort = 80;//http的端口号
/*扫描并读取tm1650中的按键码 */
char getLightSetting() {
HTTPClient http;
http.begin("http://api.heclouds.com/devices/504958608/datastreams/lighton");
http.addHeader("api-key", "ZyqMVZhU1MS0=5EFGo3uywkVg8o=");
int httpCode = http.GET();
if (httpCode != 200)
{
return -1;
}
else
{
String responseBody = http.getString();
//Serial.println(responseBody);
int l = responseBody.indexOf("\"current_value\"");
return responseBody[l + 16] - '0';
}
}
char buttonReading(void)
{
char buttonCode=0x00;
Wire.beginTransmission(0x00); //确认从机的地址开始传输
Wire.write(0x49); //发送读取键盘码的指令
Wire.requestFrom(0x24,1,0); //主机请求数据
buttonCode=Wire.read();
Wire.endTransmission(); //结束传输
return buttonCode;
}
/*根据按键来改变对应数码管的值(第一个)*/
void addDisplay0(char line[4])
{
line[0]+=1;
if(line[0]>0x39) line[0]=0x30; //0x39是9的ascii码 0x30是0的ascii码
d.displayString(line);
}
/*根据按键来改变对应数码管的值(第二个)*/
void addDisplay1(char line[4])
{
line[1]+=1;
if(line[1]>0x39) line[1]=0x30;
d.displayString(line);
}
/*根据按键来改变对应数码管的值(第三个)*/
void addDisplay2(char line[4])
{
line[2]+=1;
if(line[2]>0x39) line[2]=0x30;
d.displayString(line);
}
/*根据按键来改变对应数码管的值(第四个)*/
void addDisplay3(char line[4])
{
line[3]+=1;
if(line[3]>0x39) line[3]=0x30;
d.displayString(line);
}
/*根据获得的扫描码来确定生效的按键*/
void keyJudge(char buttoncode,char line[4])
{
switch(buttoncode)
{
case BUTTON_4: Serial.println("k4");addDisplay3(line);break;
case BUTTON_3: Serial.println("k3");addDisplay2(line);break;
case BUTTON_2: Serial.println("k2");addDisplay1(line);break;
case BUTTON_1: Serial.println("k1");addDisplay0(line);break;
default:Serial.println("nothing");break;
}
}
void setup() {
// put your setup code here, to run once:
Serial.println();
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);
/* Explicitly set the ESP8266 to be a WiFi-client, otherwise, it by default,
would try to act as both a client and an access-point and could cause
network-issues with your other WiFi-devices on your WiFi-network. */
//开始连接wifi
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());//打印IP地址
Wire.begin();
Serial.begin(9600);
pinMode(BUILTIN_LED, OUTPUT);
WiFi.begin("Call me purity", "88888888"); // WiFi of ***
// Serial.println("TM1650 Example Code");
d.init(); //初始化
d.displayOff();
d.setBrightness(TM1650_MAX_BRIGHT); //设定亮度
d.displayOn();
//d.displayString("1234");
delay(2000);
d.displayString(line);
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(5000);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
//没有搜寻到地址
if ( !ds.search(addr))
{
Serial.println("No more addresses.");
Serial.println();
ds.reset_search();//重置搜寻
delay(2500);
return;//从头进行循环
}
//显示ROM的64位序列号
Serial.print("ROM =");
for( byte i = 0; i < 8; i++) {
Serial.write(' ');
Serial.print(addr[i], HEX);
}
//进行crc检验
//::是c++的用法
if (OneWire::crc8(addr, 7) != addr[7]) {
Serial.println("CRC is not valid!");
return;
}
Serial.println();
if(addr[0]==0x28)
{
d.displayString("----");
}
}
int value = 0;
void loop() {
delay(5000);
++value;
byte i;
byte present = 0;
byte type_s;
byte data[12];
byte addr[8];
float celsius, fahrenheit;
//没有搜寻到地址
if ( !ds.search(addr)) {
Serial.println("No more addresses.");
Serial.println();
ds.reset_search();//重置搜寻
delay(250);
return;//从头进行循环
}
//显示ROM的64位序列号
Serial.print("ROM =");
for( i = 0; i < 8; i++) {
Serial.write(' ');
Serial.print(addr[i], HEX);
}
//进行crc检验
//::是c++的用法
if (OneWire::crc8(addr, 7) != addr[7]) {
Serial.println("CRC is not valid!");
return;
}
Serial.println();
//判别芯片型号
switch (addr[0]) {
case 0x10:
Serial.println(" Chip = DS18S20"); // or old DS1820
type_s = 1;
break;
case 0x28:
Serial.println(" Chip = DS18B20");
type_s = 0;
break;
case 0x22:
Serial.println(" Chip = DS1822");
type_s = 0;
break;
default:
Serial.println("Device is not a DS18x20 family device.");
return;
}
ds.reset();//在连接任何设备之前需要reset
ds.select(addr);//选择设备地址
ds.write(0x44, 1); //开始转换,并拉高数据线一段时间
delay(1000); // maybe 750ms is enough, maybe not
// we might do a ds.depower() here, but the reset will take care of it.
present = ds.reset();//present为1则表示转换完成,为0则没有
ds.select(addr);
ds.write(0xBE); //读取数据
Serial.print(" Data = ");
Serial.print(present, HEX);
Serial.print(" ");
for ( i = 0; i < 9; i++) { // we need 9 bytes
data[i] = ds.read();
Serial.print(data[i], HEX);
Serial.print(" ");
}
//CRC校验
Serial.print(" CRC=");
Serial.print(OneWire::crc8(data, 8), HEX);
Serial.println();
// Convert the data to actual temperature
// because the result is a 16 bit signed integer, it should
// be stored to an "int16_t" type, which is always 16 bits
// even when compiled on a 32 bit processor.
//进行数据转换
int16_t raw = (data[1] << 8) | data[0];
if (type_s) {
raw = raw << 3; // 9 bit resolution default
if (data[7] == 0x10) {
// "count remain" gives full 12 bit resolution
raw = (raw & 0xFFF0) + 12 - data[6];
}
} else {
byte cfg = (data[4] & 0x60);
// at lower res, the low bits are undefined, so let's zero them
if (cfg == 0x00) raw = raw & ~7; // 9 bit resolution, 93.75 ms
else if (cfg == 0x20) raw = raw & ~3; // 10 bit res, 187.5 ms
else if (cfg == 0x40) raw = raw & ~1; // 11 bit res, 375 ms
default is 12 bit resolution, 750 ms conversion time
}
celsius = (float)raw / 16.0;
fahrenheit = celsius * 1.8 + 32.0;
TEMP = (float)raw / 16.0;
char temp[]="";
dtostrf(TEMP*100,4,0,temp);
d.displayString(temp);
d.setDot(1,1);
Serial.print(" Temperature = ");
Serial.print(celsius);
Serial.print(" Celsius, ");
Serial.print(fahrenheit);
Serial.println(" Fahrenheit");
String postdata = String("")+"{\"temp1value\":"+celsius+",\"temp2value\":"+fahrenheit+"}";
Serial.print("connecting to ");
Serial.println(host);
// Use WiFiClient class to create TCP connections
//与网址建立连接
WiFiClient client;
if (!client.connect(host, httpPort)) {
Serial.println("connection failed");
return;
}
// We now create a URI for the request
//传输数据
String url = "/devices/504958608/datapoints?type=3";
Serial.print("Requesting URL: ");
Serial.println(url);
// This will send the request to the server
client.print(String("POST ") + url + " HTTP/1.1\r\n" +
"api-key:ZyqMVZhU1MS0=5EFGo3uywkVg8o=\r\n"+
"Host:" + host + "\r\n" +
"Content-Length:"+postdata.length()+"\r\n\r\n"+
postdata+"\r\n");
unsigned long timeout = millis();
//连接超时
while (client.available() == 0) {
if (millis() - timeout > 5000) {
Serial.println(">>> Client Timeout !");
client.stop();
return;
}
}
//读取云平台发送的数据,在串口监视器看见"errno": 0,"error":“succ”代表传输成功
// Read all the lines of the reply from server and print them to Serial
while(client.available()){
String line = client.readStringUntil('\r');
Serial.print(line);
}
Serial.println();
Serial.println("closing connection");
delay(1000);
if (WiFi.status() != WL_CONNECTED)
{
Serial.println("No WiFi");
}
else
{
char on = getLightSetting();
digitalWrite(BUILTIN_LED, !on);
}
}