Thursday, April 13, 2017

Temperature and hygrometer with FlashAir + Arduino + Raspberry Pi (3) : Send measured data from Arduino to Raspberry Pi

Table of contents.
  1. Read values from sensor
  2. Read from SD card with iSDIO
  3. Send values from arduino to Raspbery Pi
  4. Visualize on Raspberry Pi

It's readied to use FlashAir from Arduino.
Let's send data via Flash Air to Raspberry Pi.
The all of following source code is put in Github.

Connect arduino and Flash Air



The each function of SD card pins is as follows.
I use 4th pin as the chip select pin.
SilkFunction
CDDo not use
CSChip select
CLKClock
SDOOutput
SDIInput
GNDGround
3.3V3.3V power
5V5V power


Read a parameter file from FlashAir storage

Read a parameter from a file on SD card volume.

The parameter is ID number of a target location.
Its file name is "id.txt".
A single number (Location ID) is written in the file.

Temperature and humidity values are stored with Location ID in Raspberry Pi.
When an arduino measures at another place, you can modify the location ID in Flash Air.
So then, several places can be measured by a single arduino.

To be honest, I wanted to store all WiFi parameters in SD card, but the memory of arduino became depleted and arduino became unstable...

// Include SD card library
#include 
#include 

// Chip select
#define CHIP_SELECT_PIN 4

// File path
#define ID_FILE "/id.txt"

int ID = 0;

// Read file from SD
char* SD_read( char* path, char* buf, size_t s ) {

  delay(1000);

  File file = SD.open(path,FILE_READ);
  if ( !file ) { return ""; }

  String str = "";
  while (file.available()) { str += char(file.read()); }
  file.close();

  str.toCharArray(buf, s);

  return buf;
}

// Setup SD card
void setup_SD() {
  // Initialize SD card.
  Serial.println(F("Initializing SD card..."));  

  // SS ピンを出力にしておかないと SD カードライブラリが動作しないらしい
  // SS pin must be output to activate SD card library.
  pinMode(SS, OUTPUT);
  if (!SD.begin(CHIP_SELECT_PIN)) {
    Serial.println(F("Card failed, or not present"));
    abort();
  }

    : 

  // Convert text to integer.
  char buf[32];
  ID = atoi(SD_read(ID_FILE,buf,32));
  Serial.print(F("ID="));
  Serial.println(ID);

}

void setup() {
  // Initialize UART for message print.
  Serial.begin(9600);
  while (!Serial) {
    ;
  }

  setup_SD();
}


Wake up WiFI only at sending data

Since power consumption is intense if WiFi keeps running, leave it off when not in use.

#include 
#include 

// Interval of measurement
#define LOG_INTERVAL 600000

char SSID[] = "{WiFi SSID}";
char NETWORKKEY[] = "{WiFi password}";
char API_HOST[] = "{IP address of Raspberry Pi}";
char API_PATH[] = "/api.php";

uint8_t buffer[512];
uint32_t nextSequenceId = 0;

// Use iSDIO_waitResponse of Flash Air tutorial
boolean iSDIO_waitResponse(uint32_t sequenceId) {
  :
}

// Use iSDIO_disconnect of Flash Air tutorial
boolean iSDIO_disconnect(uint32_t sequenceId) {
  :
}

// Use iSDIO_connect of Flash Air tutorial
boolean iSDIO_connect(uint32_t sequenceId, const char* ssid, const char* networkKey) {
  :
}

// Modify iSDIO_http of tutorial.
// Target address and parameters are acceptable as arguments.
boolean iSDIO_http(uint32_t sequenceId, char* host, char* path, char* param) {
  Serial.println(F("http command: "));
  memset(buffer, 0, 512);
  uint8_t* p = buffer;
  p = put_command_header(p, 1, 0);

  // 0x21 means "Without SSL"
  p = put_command_info_header(p, 0x21, sequenceId, 2);

  // Target host is the IP address of Raspberry Pi
  p = put_str_arg(p, host);  // Argument #1.

  // HTTP header
  char getParam[128];
  sprintf(getParam,
    "GET %s?%s HTTP/1.1\r\n"
    "Host: %s\r\n"
    "User-Agent: FlashAir\r\n"
    "\r\n", path, param, host);
  Serial.println(getParam);
  p = put_str_arg(p, getParam);
  put_command_header(buffer, 1, (p - buffer));
  return SD.card.writeExtDataPort(1, 1, 0x000, buffer) ? true : false;
}

// Setup SD
void setup_SD() {
  // Initialize SD card.
  Serial.println(F("Initializing SD card..."));  

  pinMode(SS, OUTPUT);
  if (!SD.begin(CHIP_SELECT_PIN)) {
    Serial.println(F("Card failed, or not present"));
    abort();
  }
 
  // Read the previous sequence ID.
  if (SD.card.readExtMemory(1, 1, 0x420, 0x34, buffer)) {
    if (buffer[0x20] == 0x01) {
      nextSequenceId = get_u32(buffer + 0x24);
      iSDIO_waitResponse(nextSequenceId);
      nextSequenceId++;
    } else {
      nextSequenceId = 0; 
    }
  } else {
    Serial.println(F("Failed to read status."));
    nextSequenceId = 0; 
  }

  char buf[32];
  ID = atoi(SD_read(ID_FILE,buf,32));
  Serial.print(F("ID="));
  Serial.println(ID);
  }
}

void setup() {
  // Initialize UART for message print.
  Serial.begin(9600);
  while (!Serial) {
    ;
  }

  setup_SD();
}

void loop() {

  // Measure time
  unsigned long start = millis();
  digitalWrite(13,HIGH);

  //  Measure temperature and humidity
 int chk = DHT.read22(DHT_PIN);
  if ( chk != 0 ){
    Serial.println(F("Fail to read humidity."));
    delay(1000);
    return;
  }

  // Make HTTP parameters
  char humid[8];
  char temp[8];
  char param[32];
  sprintf(param,"ID=%d&H=%s&T=%s",
    ID,dtostrf(DHT.humidity,5,2,humid),dtostrf(DHT.temperature,5,2,temp));
  Serial.print(F("PARAM:"));
  Serial.println(param);

  // Wake up WiFi
  // If it fails, retry it three times.
  for ( int retry = 3; retry > 0; retry -- ) {
    delay(1000);
    if( iSDIO_connect(nextSequenceId, SSID, NETWORKKEY) &&
      iSDIO_waitResponse(nextSequenceId) ) {
      Serial.println(F("Connected"));
      retry = 0;
    } else {
      Serial.print(F("Failed or waiting. errorCode="));
      Serial.println(SD.card.errorCode(), HEX);
    }
    nextSequenceId++;
  }

  // HTTP GET
  for ( int retry = 3; retry > 0; retry -- ) {
    delay(1000);
    if ( iSDIO_http(nextSequenceId,API_HOST,API_PATH,param) &&
      iSDIO_waitResponse(nextSequenceId)) {
        Serial.println(F("OK"));
        retry = 0;
    } else {
      Serial.print(F("Failed or waiting. errorCode="));
      Serial.println(SD.card.errorCode(), HEX);
    }
    nextSequenceId++;
  }

  //Stop WiFi
  if (iSDIO_disconnect(nextSequenceId) &&
      iSDIO_waitResponse(nextSequenceId)) {
    Serial.println(F("Success."));
  } else {
    Serial.print(F("Failed or waiting. errorCode="));
    Serial.println(SD.card.errorCode(), HEX);
  }
  nextSequenceId++;

  digitalWrite(13,LOW);

  // Sleep until the next time
  unsigned long span = millis() - start;
  if ( span > LOG_INTERVAL ) { return; }
  unsigned long sleep_time = LOG_INTERVAL - span;
  Serial.print(F("SLEEP => "));
  Serial.println(sleep_time,DEC);

  // Power save
  delaySleep(sleep_time);
}


Power saving wait

Since measuring and sending ends in a few seconds, most of the time is waiting time.

In order to appropriately save power, it is necessary to isolate the power supply with relays and to stop FlashAir and DHT22 while Arduino is stopped.
Then stop Arduino using WDT (Watch Dog).

However, that is troublesome...
So, I reduced just a little power only for delay .

void delaySleep(unsigned long t) {
  unsigned long t0;
  if( t <= 16 ) {
    delay(t);
  }
  else{
    t0 = millis();
    set_sleep_mode (SLEEP_MODE_IDLE);
    while( millis() - t0 < t ) {
      sleep_mode();
    }
  }
}


The Arduino side is now complete!
However, it fails to connect...of course.
There are no target host.

Next time, we will set Raspberry Pi up as host.

3 comments:

  1. Various payment methods are accepted at El Royale; ought to use|you have to use} a debit/credit card, Neosurf, PayID, Ethereum, and Bitcoin. Once withdrawn, funds can take a lot as} five enterprise days 파라오카지노 to get to you, relying on the method chosen. Withdrawals via crypto usually take forty eight hours to reach, which is the usual among most roulette online casinos.

    ReplyDelete
  2. Remember that one spin will usually be done inside a few of} seconds. Here are the main things we thought of when looking down the top free spin promos. If you need more information, be sure to|make certain to|remember to} a glance at|try} our guide on the most effective casino bonuses. Compared to most free spins casinos, this supply stands out as distinctive because of|as a result of} you need to|you should|you have to} make three deposits to obtain the whole one hundred fifty free spins. Lucky Tiger's bonus is an honest supply in comparison with} different casino free spins bonuses we 배당사이트 tried out.

    ReplyDelete
  3. Launched in 2013, Slots.lv has rapidly become one of the top online playing companies within the industry. Its excellent provide of online slots with different themes, categories, and in-game bonuses makes it a top choice for any slot-lover. The bonus part is another engaging function players will come to love after they visit this casino. The actual cash casino video games 토토사이트 on Ignition are from 13 main providers within the industry. There is a complete of eight poker video games, all of them of very prime quality – an enormous benefit for poker lovers. There are quite a few poker tournaments being held on Ignition, making certain an excellent expertise.

    ReplyDelete