Arduino で気圧をSDカードに保存して、Webからグラフを閲覧します。
まだ書きかけ中ですが。
たぶん、ESP32で書いたほうがいいかもです。
pressureGraph.ino
/*
Web Server
A simple web server that shows the value of the analog input pins.
using an Arduino Wiznet Ethernet shield.
Circuit:
* Ethernet shield attached to pins 10, 11, 12, 13
* Analog inputs attached to pins A0 through A5 (optional)
created 18 Dec 2009
by David A. Mellis
modified 9 Apr 2012
by Tom Igoe
modified 02 Sept 2015
by Arturo Guadalupi
*/
# include <Wire.h>
// setting bmp180 ( pressure sensor )
# include <SFE_BMP180.h>
SFE_BMP180 bmp180; // SDA:A4 SDL:A5
// setting sd
# include <SD.h>
File myFile;
// setting date pin
# define CLK_PIN 8 // CLK:8番ピン
# define DAT_PIN 9 // DAT:9番ピン
# define RST_PIN 10 // RST:10番ピン
// setting date format
struct DateTime{
boolean CH; //1でClockHalt(停止)だが、0を入れてこの機能使わない前提
boolean Mode12; //1で12時間表示だが、0を入れて24時間表示で使う前提
boolean WP; //1でWriteProtectだが0を入れてこの機能使わない前提
int Date;
int Month;
int Week;
int Year;
int Seconds;
int Minutes;
int Hour;
};
// setting ethernet
# include <SPI.h>
# include <Ethernet.h>
byte mac[] = {
0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED
};
IPAddress ip(192, 168, 0, 177);
EthernetServer server(80);
IPAddress myDns(192, 168, 0, 1);
void setup() {
// setting serial band
Serial.begin(9600);
while (!Serial) {
}
//Serial.println("Serial init success");
// setting ethernet
Ethernet.begin(mac, ip , myDns );
if (Ethernet.hardwareStatus() == EthernetNoHardware) {
Serial.println("Ethernet shield was not found. Sorry, can't run without hardware. :(");
while (true) {
delay(1); // do nothing, no point running without Ethernet hardware
}
}
if (Ethernet.linkStatus() == LinkOFF) {
//Serial.println("Ethernet cable is not connected.");
}
Serial.println("Ethernet init success");
// start the server
server.begin();
//Serial.println(Ethernet.localIP());
// setting bmp180 ( pressure sensor )
bool success = bmp180.begin();
if (success) {
//Serial.println("BMP180 init success");
}
// setting sd card
if (!SD.begin(4)) {
while (1);
}
//Serial.println("SD init success");
}
void loop() {
Serial.println("loop init success");
// web server
EthernetClient client = server.available();
if (client) {
Serial.println("client init success");
boolean currentLineIsBlank = true;
while (client.connected()) {
if (client.available()) {
char c = client.read();
Serial.write(c);
if (c == '\n' && currentLineIsBlank) {
Serial.println("html init success");
client.println("HTTP/1.1 200 OK");
client.println("Content-Type: text/html");
client.println("Connection: close");
client.println("Refresh: 5");
client.println();
client.println("<!DOCTYPE HTML>");
client.println("<html>");
//
myFile = SD.open("test.txt");
if (myFile) {
while (myFile.available()) {
client.print(myFile.read());
client.println("<br/>");
}
// ここにグラフを書く
//client.println("<td><img src=\"https://chart.googleapis.com/chart?chs=100x60&cht=gom&chd=t:"+ String( int( digitalRead(i) * 100 ) ) +"&chco=FFFFFF,000000\"></td>");
myFile.close();
}
client.println("</html>");
break;
}
if (c == '\n') {
// you're starting a new line
currentLineIsBlank = true;
} else if (c != '\r') {
// you've gotten a character on the current line
currentLineIsBlank = false;
}
}
}
// give the web browser time to receive the data
delay(1);
// close the connection:
client.stop();
}
// time
byte RTC_clock_image[8];
DateTime myDateTime;
read_rtc_byte(RTC_clock_image);
extract_datetime(RTC_clock_image,myDateTime);
//yyyy-mm-dd hh:ss:ii week
/*
Serial.print(myDateTime.Year); Serial.print("-");
Serial.print(myDateTime.Month); Serial.print("-");
Serial.print(myDateTime.Date); Serial.print(" ");
Serial.print(myDateTime.Hour); Serial.print(":");
Serial.print(myDateTime.Minutes); Serial.print(":");
Serial.print(myDateTime.Seconds); Serial.print("(");
Serial.print(myDateTime.Week); Serial.println(")");
*/
// pressure
char status;
double T, P;
bool success = false;
status = bmp180.startTemperature();
//Serial.println("bmp189 init");
if (status != 0) {
//Serial.println("bmp189 init success");
delay(1000);
status = bmp180.getTemperature(T);
if (status != 0) {
status = bmp180.startPressure(3);
//Serial.println("bmp189 startPressure init");
if (status != 0) {
delay(status);
status = bmp180.getPressure(P, T);
if (status != 0) {
//Serial.println("bmp189 startPressure get success");
/*
Serial.print("Pressure: ");
Serial.print(P);
Serial.println(" hPa");
Serial.print("Temperature: ");
Serial.print(T);
Serial.println(" C");
*/
// sd card write
myFile = SD.open("test.txt", FILE_WRITE);
if (myFile) {
Serial.println("sd open success");
myFile.print(myDateTime.Year); myFile.print("-");
myFile.print(myDateTime.Month); myFile.print("-");
myFile.print(myDateTime.Date); myFile.print(" ");
myFile.print(myDateTime.Hour); myFile.print(":");
myFile.print(myDateTime.Minutes); myFile.print(":");
//myFile.print(myDateTime.Seconds); myFile.print("(");
//myFile.print(myDateTime.Week); myFile.print(")");
myFile.print(" ");
myFile.print(P);
myFile.print(" ");
myFile.println(T);
myFile.close();
}
}
}
}
}
}
// ========================================================================
// set read date functions
// ========================================================================
//RTCからクロックデータをまるごと読みだし、
byte read_rtc_byte(byte image[]){
pinMode(DAT_PIN, OUTPUT);//DAT_PINのpinmodeをまず送信用で準備
digitalWrite(RST_PIN, LOW);wait();//最初はRST_PIN下げた状態
digitalWrite(RST_PIN, HIGH);wait();//開始(RST_PIN 上げ)
write_1byte(0xbf);//バーストモードのコマンド0xbf送信
//読み出しに移るのでDAT_PINのピンモード切り替える。CLK_PIN上げのまま
pinMode(DAT_PIN, INPUT);
//8byte分続けて読みbyte配列のimageに入れる
for (int i=0; i<=7; i++){
read_1byte(image[i]);
}
//RST_PIN下げる
digitalWrite(RST_PIN, LOW); wait();
}
void write_1byte(byte data){
//コマンド等送信 1ビットずつ繰り返し8ビット(1バイト)分送る
for (int i=0; i <= 7; i++){
digitalWrite(CLK_PIN, LOW);wait(); //LOW確認
digitalWrite( DAT_PIN, bitRead(data, i));wait();
digitalWrite(CLK_PIN, HIGH);wait(); //クロック(LOWからHIGH)で書き込む
//クロック上げたままで関数を抜ける。
}
}
void read_1byte(byte &data){
//データ受信 1ビットずつ繰り返し8ビット(1バイト)分読みだす
data = 0;
for (int i=0; i<=7; i++){
digitalWrite(CLK_PIN, HIGH);wait();//clock上げ。(上げたまま引き継いだ時はそのまま)
digitalWrite(CLK_PIN, LOW);wait();//clock下げて、
bitWrite( data,i, digitalRead(DAT_PIN));//読む
//クロック下げた状態で関数を抜ける
}
}
void setImage(byte command, byte image){ //コマンド、書き込みデータ
pinMode(DAT_PIN, OUTPUT);//DAT_PINのpinmodeを送信用で準備
digitalWrite(RST_PIN, LOW);wait();//最初はRST_PIN下げた状態
digitalWrite(RST_PIN, HIGH);wait();//開始(RST_PIN 上げ)
write_1byte(command);
write_1byte(image);
digitalWrite(CLK_PIN, LOW);wait();//clock下げて、
digitalWrite(RST_PIN, LOW);wait();//最後はRST_PIN下げる
}
void getImage(byte command, byte &image){
pinMode(DAT_PIN, OUTPUT);//DAT_PINのpinmodeを送信用で準備
digitalWrite(RST_PIN, LOW);wait();//最初はRST_PIN下げた状態
digitalWrite(RST_PIN, HIGH);wait();//開始(RST_PIN 上げ)
write_1byte(command);
pinMode(DAT_PIN, INPUT);//DAT_PINのpinmodeを受信用に切り替え
read_1byte(image);
digitalWrite(RST_PIN, LOW);wait();//最後はRST_PIN下げる
}
void wait(){
//Vcc5Vなのでデータシート11ページから待ち時間は1μ秒分とっておけばよい。
delayMicroseconds(1);
}
//byte配列からの情報抽出
void extract_datetime(byte image[], DateTime &TempDateTime){
int data10, data1;
//秒
data10 = (image[0]>>4)&7; //上位4ビットを0111でマスクする。
data1 = image[0] & 15; //下位4ビットを1111でマスクする。
TempDateTime.Seconds = (data10 * 10) + data1;
TempDateTime.CH = image[0]>>7;
//分
data10 = (image[1]>>4)&7; //上位4ビットを0111でマスクする。
data1 = image[1] & 15; //下位4ビットを1111でマスクする。
TempDateTime.Minutes = (data10 * 10) + data1;
//時
data10 = (image[2]>>4)&3; //上位4ビットを0011でマスクする。
data1 = image[2] & 15; //下位4ビットを1111でマスクする。
TempDateTime.Hour = (data10 * 10) + data1;
TempDateTime.Mode12 = image[2]>>7; //12時間表示モード。0にして使わない。
//日
data10 = (image[3]>>4)&3; //上位4ビットを0011でマスクする。
data1 = image[3] & 15; //下位4ビットを1111でマスクする。
TempDateTime.Date = (data10 * 10) + data1;
//月
data10 = (image[4]>>4)&1; //上位4ビットを0001でマスクする。
data1 = image[4] & 15; //下位4ビットを1111でマスクする。
TempDateTime.Month = (data10 * 10) + data1;
//曜日
TempDateTime.Week =image[5];
//年
data10 = (image[6]>>4) & 15; //上位4ビットを1111でマスクする。
data1 = image[6] & 15; //下位4ビットを1111でマスクする。
TempDateTime.Year = (data10 * 10) + data1 + 2000;
//WP
TempDateTime.WP =image[7]>>7;
}
// ========================================================================
// set yyyy m d h s i
// ========================================================================
void setYear(int year){ // (ex. 2020
setImage(0x8C, (((year - 2000)/10)<<4)+(year % 10));
}
void setWeek(byte Week){ // 1:月 2:火 3:水 4:木 5:金 6:土 7:日
setImage(0x8A, Week);
}
void setMonth(int month){ // 1 - 12
setImage(0x88,((month/10)<<4)+(month % 10));
}
void setDate(int date){
setImage(0x86,((date/10)<<4)+(date % 10));
}
void setHour(int hour){ // 0 - 23
setImage(0x84,((hour/10)<<4)+(hour % 10));
}
void setMinutes(int minutes){
setImage(0x82,((minutes/10)<<4)+(minutes % 10));
}
void setSeconds(int seconds){
setImage(0x80,((seconds/10)<<4)+(seconds % 10));
}
~~~~