Next in my series of Arduino Yún tutorials is a guide on how to send your own data from the Yún to a Google Docs spreadsheet. This builds on the original example by showing how to send data from the analogue and digital inputs, as well as from a real-time clock connected via I2C.
Any recommendations on how to tweak this to log to the sd card and then periodically send a batch of data to google docs? I'm thinking this saves on transmission energy, maybe? Maybe not actually...because it is always on. Hmm.
I still wish I had an easy way to power down the atheros board when I'm not using it. I'm Considering an external module to power the Yun (the whole thing) up every x minutes and power it down after receiving a confirmation (eg pin high). Seems silly but I have no continuous power.
Anyway. Sorry about the rant. I think I will use a stream to open a data file and upload the whole file as strings by line and then when successful, I'll start logging to a new file. I'll store the name if that file in yun's memory so I know which one to upload each time. Or perhaps it is better to enumerate the file name so the code will just look for the file with the highest number and upload that one. Hmm.
In any event, thanks for the tut. Bring us a long way towards a micro datalogger and transmitter.
#!/usr/bin/python
import gspread
# Login with your Google account
gc = gspread.login('abc@gmail.com', 'googlepassword')
sh = gc.open_by_key('0Ao9lSur2AThldE1uQk1MVGtWS25vRTBuTXM4NWpGRFE')
wks= sh.get_worksheet(0)
wks.update_acell('B2', "it's down there somewhere, let me take another look.")
Almost perfectly. It works fine when I run the python code from a console. When I try to run the python code from a Process, the data doesn’t show up in the spreadsheet. Instead of numbers, it shows “NONE” in the cells. Here’s the Arduino code:
// This sketch sends temperature and humidity data to the Linux side of an Arduino Yun.
#include <Process.h>
#include <DHT.h>
#include <FileIO.h>
#define LEDpin 13
#define DHTTYPE DHT22 // DHT 22 (AM2302 wired temperature and humidity sensor)
#define DHTPIN 7 // The DHT output is connected to digital pin 7.
DHT dht(DHTPIN, DHTTYPE); //define the DHT object
// set up net client info:
const unsigned long postingInterval = 60000; //delay between updates
unsigned long lastRequest = 0; // when you last made a request
String logString;
void setup() {
Bridge.begin();
FileSystem.begin();
pinMode(DHTPIN, INPUT);
pinMode(LEDpin, OUTPUT);
dht.begin(); // Start reading from the AM2302 temperature and humidity sensor
// disable wifi for this sketch
Process wifiDisable;
wifiDisable.runShellCommand("wifi down");
Process wifiCheck;
wifiCheck.runShellCommand("/usr/bin/pretty-wifi-info.lua");
String msgString;
while (wifiCheck.available() > 0) {
char c = wifiCheck.read();
msgString += c;
}
File logFile = FileSystem.open("/mnt/sda1/arduino/log.txt", FILE_APPEND);
logFile.println(getTimeStamp());
logFile.println(msgString);
logFile.close();
Process startPython;
startPython.runShellCommand("python /mnt/sda1/DHTbridgetest.py");
// Do a first update immediately
updateData();
lastRequest = millis();
}
void loop() {
// get a timestamp so you can calculate reading and sending intervals:
long now = millis();
// if the sending interval has passed since your
// last connection, then connect again and send data:
if (now - lastRequest >= postingInterval) {
updateData();
lastRequest = now;
}
}
void updateData() {
// read sensor values
float dhtTemperature = dht.readTemperature();
float dhtHumidity = dht.readHumidity();
String timestamp = getTimeStamp();
// send data to Linux processor
Bridge.put("timestamp", timestamp);
Bridge.put("temperature", String(dhtTemperature));
Bridge.put("humidity", String(dhtHumidity));
logString = String(dhtTemperature);
logString += ", ";
logString += dhtHumidity;
File dataFile = FileSystem.open("/mnt/sda1/arduino/dhtdata.txt", FILE_APPEND);
dataFile.print(timestamp);
dataFile.print(", ");
dataFile.println(logString);
dataFile.close();
}
// This function returns a string with the time stamp
String getTimeStamp() {
String result;
Process time;
// date is a command line utility to get the date and the time
// in different formats depending on the additional parameters
time.begin("date");
time.addParameter("+%d/%m/%y %T"); // parameters: +%d/%m/%y for the complete date dd/mm/yy
// T for the time hh:mm:ss
time.run(); // run the command
// read the output of the command
while (time.available() > 0) {
char c = time.read();
if (c != '\n')
result += c;
}
return result;
}
Here’s the python code:
#!/usr/bin/python
import gspread
import time
import sys
sys.path.insert(0, '/usr/lib/python2.7/bridge/')
from bridgeclient import BridgeClient as bridgeclient
value = bridgeclient()
# Login with your Google account
gc = gspread.login('address@gmail.com', 'password')
sh = gc.open_by_key('spreadsheet key here')
wks= sh.get_worksheet(0)
try:
while True:
# read data from Arduino side of the Yun
timestamp = value.get('timestamp')
temperature = value.get('temperature')
humidity = value.get('humidity')
# print formatted data to console
print("{0:20}{1:12}{2:12}".format("Time","Temperature","Humidity"))
print("{0:20}{1:12}{2:12}".format(timestamp,temperature,humidity))
print
# send data to Google Drive spreadsheet
wks.append_row([timestamp, temperature, humidity])
time.sleep(60)
except KeyboardInterrupt:
print("\ndone")
Thanks. I tried this and it didn't work though. I think that the while loop will never get executed because timestamp will always equal zero ("timestamp = value.get('timestamp')" will never execute, so the value of timestamp won't change).
What did work though, is that I put a line in the rc.local file to get the python script to start on boot of Linino:
# Put your custom commands here that should be executed once
# the system init finished. By default this file does nothing.
python /mnt/sda1/DHTbridgetest.py
wifi-live-or-reset
exit 0
Thanks for your help. I wouldn't have gotten this to work without it.
Thanks. I did something similar to that. Also, if anyone else is watching this thread, another way to keep a python script running after you've started it in a console window is to add a "&" to the end of the command to get the script to run in the background:
python /mnt/sda1/pythoncode.py&
timestamp = 0
temperature = 0
humidity = 0
try:
while True:
# read data from Arduino side of the Yun
timestamp = value.get('timestamp')
temperature = value.get('temperature')
humidity = value.get('humidity')
if timestamp != 0:
# print formatted data to console
#print("{0:20}{1:12}{2:12}".format("Time","Temperature","Humidity"))
#print("{0:20}{1:12}{2:12}".format(timestamp,temperature,humidity))
#print
#write data to a file
file=open('/mnt/sda1/pythondata.txt','a')
line= "{0:20}{1:12}{2:12}".format(timestamp,temperature,humidity)
print >>file, line
# send data to Google Drive spreadsheet
wks.append_row([timestamp, temperature, humidity])
# set values to zero until the next time
# the arduino populates them
value.put('timestamp',0)
value.put('temperature',0)
value.put('humidity',0)
time.sleep(5)
except KeyboardInterrupt:
One thing you could try is to #include <Console.h> and use Console.print instead of Serial.print. I have not had a sketch work on the Yun where I used the Serial library. Then again, I only connect to the Yun via ethernet and haven’t tried using USB.