Commit 00dcf548 authored by Nelso Jost's avatar Nelso Jost

NEW: merged esplogger work and better structure established

parent 6c202d31
EMM Data Logger EMM Meteorolog
Copyright (C) 2015 Nelso G. Jost Copyright (C) 2015 Nelso G. Jost
This program is free software: you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
......
PORT :=
BAUD := 115200
PIOBOARD = esp12e
PIOPROJ = firmware/esplogger
PIODIR = .pio
.PHONY: firmware monitor reset getport
all: help
install-platformaio:
pip install platformio
firmware:
@ echo "$$PIO_BUILD" | sh
@ $(MAKE) monitor
monitor: getport
picocom /dev/$(PORT) -b $(BAUD)
reset: getport
@ echo "-----------------------------------------"
@ echo "Reseting the board"
esptool.py --port /dev/$(PORT) run
@ python -c "import time; time.sleep(1)"
getport:
@ $(eval PORT := `python utils/getport.py`)
@ echo $(PORT)
example-blink:
$(eval PIOPROJ := examples/blink)
@ echo "$$PIO_BUILD" | sh
example-wifiscan:
$(eval PIOPROJ := examples/wifiscan)
@ echo "$$PIO_BUILD" | sh
$(MAKE) monitor
example-sdcardinfo:
$(eval PIOPROJ := examples/sd_card_info)
@ echo "$$PIO_BUILD" | sh
$(MAKE) monitor
help:
@ echo "$$HELP_MAKEFILE"
define HELP_MAKEFILE
Usage: make <target> where <target> can be:
firmware Build and upload the esplogger firmware using platformio
monitor Start the picocom serial monitor (autodetect port)
reset Attempt a soft reset of the ESP devkit board
example-____ Build and upload one of the examples/ projects:
blink -- turn on and off the led on pin 2
wifiscan -- detect and print all available SSIDs
endef
export HELP_MAKEFILE
define PY_GET_PORT
import os
ports = [x for x in os.listdir("/dev") if x.startswith("ttyUSB")
or x.startswith("ttyACM")]
if ports and isinstance(ports[0], str):
print(ports[0])
else:
print("Error: Unable to find a ttyUSB/ttyACM serial port")
raise SystemExit(1)
endef
export PY_GET_PORT
define PIO_BUILD
mkdir -p $(PIODIR)
rm -rf $(PIODIR)/src
platformio init --board $(PIOBOARD) -d $(PIODIR)
cp -rf $(PIOPROJ)/* $(PIODIR)/src/
cd $(PIODIR) && platformio run -t upload
endef
export PIO_BUILD
Purpose
-------
Data logger firmware that runs on the ESP12e NodeMCU board connected an Arduino via software serial for sensor reading. This firmware is being designed to accomplish the following tasks:
* Read sensor data from the Arduino board (established platform for plugging sensors);
* Save the data locally onto an SD card;
* Attempt to send the data onto the server (if fail, try again later);
* Serial REPL (Read-Eval-Print-Loop) interpreter for sending commands;
** Used on initial setup and debugging tasks;
This software is part o the project EMM at CTA-UFRGS. See the official page for more details:
http://cta.if.ufrgs.br/projects/estacao-meteorologica-modular/wiki/Wiki
Usage
-----
The Makefile present on the root directory provide a quick commands for the most commom operations. Type "make" or "make help" for showing the help message. Some commands require external tools to be installed, like Platformio.
The project firmware is under the "firmware/" directory and is ArduinoIDE-compatible. Alternatively you can build/upload it via terminal using "make firmware" command, that uses the excelent PlatformIO tool (use "make install-platformio" if not present).
The examples folder contains several Arduino-IDE compatible little projects for demonstration of key features of the ESP12e.
Development
-----------
The software is still on its early stages, so new functionality will be added frequently.
#include <Arduino.h>
#define LED_PIN 2
#define SLEEP_INTERVAL 500 // milliseconds
void setup()
{
Serial.begin(115200);
pinMode(LED_PIN, OUTPUT);
}
void loop()
{
digitalWrite(LED_PIN, HIGH);
delay(SLEEP_INTERVAL);
digitalWrite(LED_PIN, LOW);
delay(SLEEP_INTERVAL);
}
#include <Arduino.h>
#define LED_PIN 2
#define SLEEP_INTERVAL 500 // milliseconds
void setup()
{
Serial.begin(115200);
pinMode(LED_PIN, OUTPUT);
}
void loop()
{
digitalWrite(LED_PIN, HIGH);
delay(SLEEP_INTERVAL);
digitalWrite(LED_PIN, LOW);
delay(SLEEP_INTERVAL);
}
/*
SD card test
This example shows how use the utility libraries on which the'
SD library is based in order to get info about your SD card.
Very useful for testing a card when you're not sure whether its working or not.
The circuit:
* SD card attached to SPI bus as follows:
** MOSI - pin 11 on Arduino Uno/Duemilanove/Diecimila
** MISO - pin 12 on Arduino Uno/Duemilanove/Diecimila
** CLK - pin 13 on Arduino Uno/Duemilanove/Diecimila
** CS - depends on your SD card shield or module.
Pin 4 used here for consistency with other Arduino examples
created 28 Mar 2011
by Limor Fried
modified 9 Apr 2012
by Tom Igoe
*/
// include the SD library:
#include <SPI.h>
#include <SD.h>
// set up variables using the SD utility library functions:
Sd2Card card;
SdVolume volume;
SdFile root;
// change this to match your SD shield or module;
// Arduino Ethernet shield: pin 4
// Adafruit SD shields and modules: pin 10
// Sparkfun SD shield: pin 8
const int chipSelect = 10;
void setup()
{
// Open serial communications and wait for port to open:
Serial.begin(115200);
while (!Serial) {
; // wait for serial port to connect. Needed for Leonardo only
}
Serial.print("\nInitializing SD card...");
// we'll use the initialization code from the utility libraries
// since we're just testing if the card is working!
if (!card.init(SPI_HALF_SPEED, chipSelect)) {
Serial.println("initialization failed. Things to check:");
Serial.println("* is a card inserted?");
Serial.println("* is your wiring correct?");
Serial.println("* did you change the chipSelect pin to match your shield or module?");
return;
} else {
Serial.println("Wiring is correct and a card is present.");
}
// print the type of card
Serial.print("\nCard type: ");
switch (card.type()) {
case SD_CARD_TYPE_SD1:
Serial.println("SD1");
break;
case SD_CARD_TYPE_SD2:
Serial.println("SD2");
break;
case SD_CARD_TYPE_SDHC:
Serial.println("SDHC");
break;
default:
Serial.println("Unknown");
}
// Now we will try to open the 'volume'/'partition' - it should be FAT16 or FAT32
if (!volume.init(card)) {
Serial.println("Could not find FAT16/FAT32 partition.\nMake sure you've formatted the card");
return;
}
// print the type and size of the first FAT-type volume
uint32_t volumesize;
Serial.print("\nVolume type is FAT");
Serial.println(volume.fatType(), DEC);
Serial.println();
volumesize = volume.blocksPerCluster(); // clusters are collections of blocks
volumesize *= volume.clusterCount(); // we'll have a lot of clusters
volumesize *= 512; // SD card blocks are always 512 bytes
Serial.print("Volume size (bytes): ");
Serial.println(volumesize);
Serial.print("Volume size (Kbytes): ");
volumesize /= 1024;
Serial.println(volumesize);
Serial.print("Volume size (Mbytes): ");
volumesize /= 1024;
Serial.println(volumesize);
Serial.println("\nFiles found on the card (name, date and size in bytes): ");
root.openRoot(volume);
// list all files in the card with date and size
root.ls(LS_R | LS_DATE | LS_SIZE);
}
void loop(void) {
}
/*
* CREDITS: https://github.com/platformio/platform-espressif8266
*
* This sketch demonstrates how to scan WiFi networks.
* The API is almost the same as with the WiFi Shield library,
* the most obvious difference being the different file you need to include:
*/
#include <Arduino.h>
#include "ESP8266WiFi.h"
void setup()
{
Serial.begin(115200);
// Set WiFi to station mode and disconnect from an AP
// if it was previously connected
// WiFi.mode(WIFI_STA);
// WiFi.disconnect();
// delay(100);
// Serial.println("Setup done");
}
void loop()
{
Serial.print("\nScanning wifi networks...");
Serial.flush();
int n = WiFi.scanNetworks();
Serial.println(" done!\n");
Serial.flush();
if (n == 0)
{
Serial.println("no networks found");
}
else
{
Serial.print(n);
Serial.println(" networks found:");
Serial.println("-------------------------");
for (int i = 0; i < n; ++i)
{
Serial.print(i + 1);
Serial.print(": ");
Serial.print(WiFi.SSID(i));
Serial.print(" (");
Serial.print(WiFi.RSSI(i));
Serial.print(")");
Serial.println((WiFi.encryptionType(i) == ENC_TYPE_NONE)?" ":"*");
delay(10);
}
}
Serial.println("");
Serial.println("Waiting 5 secs...");
Serial.flush();
// Wait a bit before scanning again
delay(5000);
}
/*
*/
#include <Arduino.h>
#include "wifi.h"
char read_char = 0;
String command = "";
void setup()
{
Serial.begin(115200);
Serial.println();
Serial.print("> ");
}
void loop()
{
if ((read_char == 13) || (command.endsWith(";")))
{
execute_board_command(command);
Serial.println();
Serial.print("> ");
command = "";
}
else
{
Serial.print(read_char);
command += read_char;
};
Serial.flush();
while (!Serial.available()) {};
read_char = Serial.read();
}
int execute_board_command(String command)
{
if (command == "wifiscan;")
{
wifiscan();
}
else if (command == "ls")
{
}
else
{
Serial.println("");
Serial.print("[Error] Invalid command: \"");
Serial.print(command);
Serial.println("\"");
}
}
/*
* CREDITS: https://github.com/platformio/platform-espressif8266
*
* This sketch demonstrates how to scan WiFi networks.
* The API is almost the same as with the WiFi Shield library,
* the most obvious difference being the different file you need to include:
*/
#include <Arduino.h>
#include "ESP8266WiFi.h"
void wifiscan(void)
{
Serial.println();
Serial.print("Scanning wifi networks...");
Serial.flush();
int n = WiFi.scanNetworks();
Serial.println(" done!\n");
Serial.flush();
if (n == 0)
{
Serial.println("no networks found");
}
else
{
Serial.print(n);
Serial.println(" networks found:");
Serial.println("-------------------------");
for (int i = 0; i < n; ++i)
{
Serial.print(i + 1);
Serial.print(": ");
Serial.print(WiFi.SSID(i));
Serial.print(" (");
Serial.print(WiFi.RSSI(i));
Serial.print(")");
Serial.println((WiFi.encryptionType(i) == ENC_TYPE_NONE)?" ":"*");
delay(10);
}
}
}
#ifndef WIFI_H
#define WIFI_H
void wifiscan(void);
#endif
BOARD := uno
PROJDIR := firmware/adafruit_bmp
PIOSETUP := python ../../utils/piosetup.py
PIODIR := .pio
.PHONY: monitor uno due nano mega clean
all:
$(MAKE) $(BOARD)
uno:
$(PIOSETUP) --board uno --project-dir $(PROJDIR) --pio-dir $(PIODIR)
$(MAKE) monitor
due:
$(PIOSETUP) --board diecimilaatmega328 --pio-dir $(PIODIR)
nano:
$(PIOSETUP) --board nanoatmega328 --pio-dir $(PIODIR)
mega:
$(PIOSETUP) --board megaatmega2560 --pio-dir $(PIODIR)
monitor:
picocom --baud $(shell $(GET_BAUD)) $(shell $(GET_PORT))
clean:
rm -rf .pio .travis.yml
define GET_BAUD
cat $(PROJDIR)/*.ino | grep '^#define BAUDRATE' | awk '{print $$3}'
endef
define GET_PORT
platformio device list | head -1
endef
/***************************************************************************
This is a library for the BMP085 pressure sensor
Designed specifically to work with the Adafruit BMP085 or BMP180 Breakout
----> http://www.adafruit.com/products/391
----> http://www.adafruit.com/products/1603
These displays use I2C to communicate, 2 pins are required to interface.
Adafruit invests time and resources providing this open source code,
please support Adafruit andopen-source hardware by purchasing products
from Adafruit!
Written by Kevin Townsend for Adafruit Industries.
BSD license, all text above must be included in any redistribution
***************************************************************************/
#ifndef __BMP085_H__
#define __BMP085_H__
#if (ARDUINO >= 100)
#include "Arduino.h"
#else
#include "WProgram.h"
#endif
#include <Adafruit_Sensor.h>
#ifdef __AVR_ATtiny85__
#include "TinyWireM.h"
#define Wire TinyWireM
#else
#include <Wire.h>
#endif
/*=========================================================================
I2C ADDRESS/BITS
-----------------------------------------------------------------------*/
#define BMP085_ADDRESS (0x77)
/*=========================================================================*/
/*=========================================================================
REGISTERS
-----------------------------------------------------------------------*/
enum
{
BMP085_REGISTER_CAL_AC1 = 0xAA, // R Calibration data (16 bits)
BMP085_REGISTER_CAL_AC2 = 0xAC, // R Calibration data (16 bits)
BMP085_REGISTER_CAL_AC3 = 0xAE, // R Calibration data (16 bits)
BMP085_REGISTER_CAL_AC4 = 0xB0, // R Calibration data (16 bits)
BMP085_REGISTER_CAL_AC5 = 0xB2, // R Calibration data (16 bits)
BMP085_REGISTER_CAL_AC6 = 0xB4, // R Calibration data (16 bits)
BMP085_REGISTER_CAL_B1 = 0xB6, // R Calibration data (16 bits)
BMP085_REGISTER_CAL_B2 = 0xB8, // R Calibration data (16 bits)
BMP085_REGISTER_CAL_MB = 0xBA, // R Calibration data (16 bits)
BMP085_REGISTER_CAL_MC = 0xBC, // R Calibration data (16 bits)
BMP085_REGISTER_CAL_MD = 0xBE, // R Calibration data (16 bits)
BMP085_REGISTER_CHIPID = 0xD0,
BMP085_REGISTER_VERSION = 0xD1,
BMP085_REGISTER_SOFTRESET = 0xE0,
BMP085_REGISTER_CONTROL = 0xF4,
BMP085_REGISTER_TEMPDATA = 0xF6,
BMP085_REGISTER_PRESSUREDATA = 0xF6,
BMP085_REGISTER_READTEMPCMD = 0x2E,
BMP085_REGISTER_READPRESSURECMD = 0x34
};
/*=========================================================================*/
/*=========================================================================
MODE SETTINGS
-----------------------------------------------------------------------*/
typedef enum
{
BMP085_MODE_ULTRALOWPOWER = 0,
BMP085_MODE_STANDARD = 1,
BMP085_MODE_HIGHRES = 2,
BMP085_MODE_ULTRAHIGHRES = 3
} bmp085_mode_t;
/*=========================================================================*/
/*=========================================================================
CALIBRATION DATA
-----------------------------------------------------------------------*/
typedef struct
{
int16_t ac1;
int16_t ac2;
int16_t ac3;
uint16_t ac4;
uint16_t ac5;
uint16_t ac6;
int16_t b1;
int16_t b2;
int16_t mb;
int16_t mc;
int16_t md;
} bmp085_calib_data;
/*=========================================================================*/
class Adafruit_BMP085_Unified : public Adafruit_Sensor
{
public:
Adafruit_BMP085_Unified(int32_t sensorID = -1);
bool begin(bmp085_mode_t mode = BMP085_MODE_ULTRAHIGHRES);
void getTemperature(float *temp);
void getPressure(float *pressure);
float pressureToAltitude(float seaLevel, float atmospheric);
float seaLevelForAltitude(float altitude, float atmospheric);
// Note that the next two functions are just for compatibility with old
// code that passed the temperature as a third parameter. A newer
// calculation is used which does not need temperature.
float pressureToAltitude(float seaLevel, float atmospheric, float temp);
float seaLevelForAltitude(float altitude, float atmospheric, float temp);
bool getEvent(sensors_event_t*);
void getSensor(sensor_t*);
private:
int32_t computeB5(int32_t ut);
int32_t _sensorID;
};
#endif
/*
* Copyright (C) 2008 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software< /span>
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* Update by K. Townsend (Adafruit Industries) for lighter typedefs, and
* extended sensor support to include color, voltage and current */
#ifndef _ADAFRUIT_SENSOR_H
#define _ADAFRUIT_SENSOR_H
#if ARDUINO >= 100
#include "Arduino.h"
#include "Print.h"
#else
#include "WProgram.h"
#endif
/* Intentionally modeled after sensors.h in the Android API:
* https://github.com/android/platform_hardware_libhardware/blob/master/include/hardware/sensors.h */
/* Constants */
#define SENSORS_GRAVITY_EARTH (9.80665F) /**< Earth's gravity in m/s^2 */
#define SENSORS_GRAVITY_MOON (1.6F) /**< The moon's gravity in m/s^2 */
#define SENSORS_GRAVITY_SUN (275.0F) /**< The sun's gravity in m/s^2 */
#define SENSORS_GRAVITY_STANDARD (SENSORS_GRAVITY_EARTH)
#define SENSORS_MAGFIELD_EARTH_MAX (60.0F) /**< Maximum magnetic field on Earth's surface */
#define SENSORS_MAGFIELD_EARTH_MIN (30.0F) /**< Minimum magnetic field on Earth's surface */
#define SENSORS_PRESSURE_SEALEVELHPA (1013.25F) /**< Average sea level pressure is 1013.25 hPa */
#define SENSORS_DPS_TO_RADS (0.017453293F) /**< Degrees/s to rad/s multiplier */
#define SENSORS_GAUSS_TO_MICROTESLA (100) /**< Gauss to micro-Tesla multiplier */
/** Sensor types */
typedef enum
{
SENSOR_TYPE_ACCELEROMETER = (1), /**< Gravity + linear acceleration */
SENSOR_TYPE_MAGNETIC_FIELD = (2),
SENSOR_TYPE_ORIENTATION = (3),
SENSOR_TYPE_GYROSCOPE = (4),
SENSOR_TYPE_LIGHT = (5),
SENSOR_TYPE_PRESSURE = (6),
SENSOR_TYPE_PROXIMITY = (8),
SENSOR_TYPE_GRAVITY = (9),
SENSOR_TYPE_LINEAR_ACCELERATION = (10), /**< Acceleration not including gravity */
SENSOR_TYPE_ROTATION_VECTOR = (11),
SENSOR_TYPE_RELATIVE_HUMIDITY = (12),
SENSOR_TYPE_AMBIENT_TEMPERATURE = (13),
SENSOR_TYPE_VOLTAGE = (15),
SENSOR_TYPE_CURRENT = (16),
SENSOR_TYPE_COLOR = (17)
} sensors_type_t;
/** struct sensors_vec_s is used to return a vector in a common format. */
typedef struct {
union {
float v[3];
struct {
float x;
float y;
float z;
};
/* Orientation sensors */
struct {
float roll; /**< Rotation around the longitudinal axis (the plane body, 'X axis'). Roll is positive and increasing when moving downward. -90°<=roll<=90° */
float pitch; /**< Rotation around the lateral axis (the wing span, 'Y axis'). Pitch is positive and increasing when moving upwards. -180°<=pitch<=180°) */
float heading; /**< Angle between the longitudinal axis (the plane body) and magnetic north, measured clockwise when viewing from the top of the device. 0-359° */
};
};
int8_t status;
uint8_t reserved[3];
} sensors_vec_t;
/** struct sensors_color_s is used to return color data in a common format. */
typedef struct {
union {
float c[3];
/* RGB color space */
struct {
float r; /**< Red component */
float g; /**< Green component */
float b; /**< Blue component */
};
};
uint32_t rgba; /**< 24-bit RGBA value */
} sensors_color_t;
/* Sensor event (36 bytes) */
/** struct sensor_event_s is used to provide a single sensor event in a common format. */
typedef struct
{
int32_t version; /**< must be sizeof(struct sensors_event_t) */
int32_t sensor_id; /**< unique sensor identifier */
int32_t type; /**< sensor type */
int32_t reserved0; /**< reserved */
int32_t timestamp; /**< time is in milliseconds */
union
{
float data[4];
sensors_vec_t acceleration; /**< acceleration values are in meter per second per second (m/s^2) */
sensors_vec_t magnetic; /**< magnetic vector values are in micro-Tesla (uT) */
sensors_vec_t orientation; /**< orientation values are in degrees */
sensors_vec_t gyro; /**< gyroscope values are in rad/s */
float temperature; /**< temperature is in degrees centigrade (Celsius) */
float distance; /**< distance in centimeters */
float light; /**< light in SI lux units */
float pressure; /**< pressure in hectopascal (hPa) */
float relative_humidity; /**< relative humidity in percent */
float current; /**< current in milliamps (mA) */
float voltage; /**< voltage in volts (V) */
sensors_color_t color; /**< color in RGB component values */
};
} sensors_event_t;
/* Sensor details (40 bytes) */