Sunday, August 24, 2014

Arduino: TempLogger

I’ve gotten terrible sleep the past 4-5 weeks. I wake up every night around 2 am, just hot and uncomfortable. I usually can’t get back to sleep once I wake up, either.

So time for another lifehack! I have an Arduino, I have an SD card logging shield, and I have a digital temp sensor – I decided to build a temperature logger and record the temps overnight.

WP_20140824_001[1]

Below is the code from my first attempt about a year ago. I broke it out again today and was looking at it – I found an article on the BMP085 online at Sparkfun, which when reading seems to indicate that you need to do a fair amount of calibration at startup in order to get accurate data. I went ahead and downloaded Sparkfun’s code and ran it – lo and behold, with all of its calculations it is still reporting the same 80 degrees my simple code is reading.

Lesson: you don’t need that calculation!

#include <Wire.h>
#include <Adafruit_BMP085.h>
#include <SD.h>
#include "Arduino.h"
#include "RTClib.h"

/**********************************************************************************
   TempLogger is an Arduino tool to log temperatures throughout a sustained time
   period. Ever wonder how well your heat is regulated? Tired of waking up hot at
   night? That's why I built templogger - my bedroom seemed awfully hot around 2
   am and, coincidentally, I kept waking up at 2 am.
  
   Requires an Arduino board, a GPS logging shield, and a BMP085 pressure/temp
   sensor from AdaFruit (
https://www.adafruit.com/products/391)
  
   See K7JTO.blogspot.com for this and other Arduino recipes.
**********************************************************************************/

/*
  Connect VCC - 3v
  Connect SCL - Analog pin #5
  Connect SDA - Analog pin #4
  Connect GND - GND (obviously)
*/

// Define Section
#define DEBUG 1                                    // Toggle 1/0 to en/disable serial out
#define led1Pin 5                                  // OPTIONAL: wire pin 5 to write LED
#define led2Pin 6                                  // OPTIONAL: wire pin 6 to read LED
#define BUFFSIZE 90                               // Create a buffer to store log file name

// Variables and Objects
Adafruit_BMP085 bmp;                                // ID for BMP085 unit
RTC_DS1307 RTC;                                     // Real-time clock object
const int chipSelect = 10;                          // Must be left as an output or SD library won't work
boolean gotSDCard = false;                          // Set to true if file successfully created
File logFile;                                       // File for logging data
char buffer[BUFFSIZE];                         // String buffer for the sentence
uint8_t i;                                          // usigned int for iterating
float currTemp = 0;                                 // Int for current temperature
String stringTemp = "";                             // String to hold temperature in
static char sprintfbuffer[15];                      // Buffer to convert float to string
static char dtostrfbuffer[15];                      // 2nd buffer to convert float to string

 

void setup() {
  Serial.begin(9600);
  if (!bmp.begin()) {
    Serial.println("Could not find a valid BMP085 sensor, check wiring!");
      return;
  }

  // Setting up the card means creating a new logging file for
  // each session, and initializing that logging file.
  if (setupSDCard()) {
    if (DEBUG) {
      Serial.println("card initialized.");
    }
    // Start RTC
    RTC.begin();
  }
}
 
void loop() {
  // Variables
  String nowTime = "";                                // String name for current time
  String dataString = "";                             // Store line for temp sensor
   
  // First grab the time from the RCT on the logging shield
  DateTime now = RTC.now();
 
  // Now build the timestamp. Should look like 12/25/2013 04:27:00"
  // Slight hack - sometimes the seconds value reads funny, and for
  // what we're doing, seconds aren't important, so just shove two
  // 0's in.
  nowTime += now.month(), DEC;
  nowTime += "/";
  nowTime += now.day(), DEC;
  nowTime += "/";
  nowTime += now.year(), DEC;
  nowTime += " ";
  nowTime += now.hour(), DEC;
  nowTime += ":";
  nowTime += now.minute(), DEC;
  nowTime += ":00";
 
  // Next grab the temp from the BMP. Problem is the temp comes in as an int, which
  // the Arduino can't convert to a string. So once the temp comes in, turn it into
  // a string via sprintf and dtostrf
  currTemp = ((bmp.readTemperature()*1.8)+32);
  sprintf(sprintfbuffer,"%f", currTemp);
  dtostrf(currTemp,8, 2, dtostrfbuffer);
 
  dataString = nowTime + "," + dtostrfbuffer;
  if(DEBUG) {
    Serial.println("Datastring: ") + dataString;
  }
   
  // Now write temp to logfile
  File dataFile = SD.open(buffer, FILE_WRITE);
   
    // if the file is available, write to it:
    if (dataFile) {
      // Light an LED
      digitalWrite(led1Pin, HIGH);
      digitalWrite(led2Pin, HIGH);
     
      // Write
      dataFile.println(dataString);
      dataFile.close();
     
      // Unlight the LED
      delay(1000);
      digitalWrite(led1Pin, LOW);
      digitalWrite(led2Pin, LOW);
     
      // print to serial port too:
      if (DEBUG) {
        Serial.println(dataString + " saved to data file");
      }
    }
    else {
      Serial.println("Error opening log file to write " + dataString);
    }
   
   // Now delay the device. This could be a sleep delay, if the device were running off
   // batteries, but a simple delay will suffice for externally-powered scenarios.
    delay(60000);
}

//** Sets up SD card. Returns true if no error **/
boolean setupSDCard() {
  // Now set up SD for logging
  // This code lifted from "Datalogger" sample sketch
  if (DEBUG)
    Serial.println("Initializing SD card...");
// make sure that the default chip select pin is set to
  // output, even if you don't use it:
  pinMode(10, OUTPUT);
// see if the card is present and can be initialized:
  if (!SD.begin(chipSelect)) {
    Serial.println("Card init. failed! chipSelect = " + chipSelect);
    error(1);
    return false;
  }
  // Now create a unique file. NOTE: IF YOU CHANGE THE FILE NAME, CHECK THAT YOUR INDEXES STILL WORK
  // (buffer[6] and buffer[7] will need to change if you change the length of the file name)
  strcpy(buffer, "TMPLOG00.TXT");
  for (i = 0; i < 100; i++) {         
    // Keep iterating till you find unique file name
    // Create if does not exist, do not open existing, write, sync after write
    buffer[6] = '0' + i/10;
    buffer[7] = '0' + i%10;
    if (! SD.exists(buffer)) {
      break;
    }
  }
  // Now open the file just created
  logFile = SD.open(buffer, FILE_WRITE);
  if( ! logFile ) {
    if (DEBUG)
    {
       Serial.print("Couldnt create "); Serial.println(buffer);
    }
    error(3);
    return false;
  }
  if (DEBUG)
  {
    Serial.print("Creating file on card: "); Serial.println(buffer);
  }
  return true;
  // Done opening log file
}

// Handling Errrs HERE
// blink out an error code
void error(uint8_t errno) {
  if (DEBUG)
  {
     Serial.print("Error encountered. Error no: ");
     Serial.print(errno);
  }
 
  // First, blink 3x fast
  blinkThrice();
 
  // Now blink errno times, slow
  for (i=0; i<=errno; i++) {
    digitalWrite(led1Pin, HIGH);
    digitalWrite(led2Pin, HIGH);
    delay(3000);
    digitalWrite(led1Pin, LOW);
    digitalWrite(led2Pin, LOW);
    delay(1000);
  }
 
  blinkThrice();
}

void blinkThrice() {
  for (i=0; i<3; i++) {
    digitalWrite(led1Pin, HIGH);
    digitalWrite(led2Pin, HIGH);
    delay(3000);
    digitalWrite(led1Pin, LOW);
    digitalWrite(led2Pin, LOW);
    delay(1000);
  }
}

/***************************************************
  Portions of this code based on Adafruit BMP085 sample code. See
  info below.

  Designed specifically to work with the Adafruit BMP085 Breakout
  ---->
https://www.adafruit.com/products/391

  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 and open-source hardware by purchasing
  products from Adafruit!

  Written by Limor Fried/Ladyada for Adafruit Industries. 
  BSD license, all text above must be included in any redistribution
****************************************************/

Sunday, August 17, 2014

High Altitude Balloon–Requirements

I’ve been toying with sending a balloon to near space. This idea has passed through my two youngest sons (neither really got interested), and now I’m looking at doing this with a NOVE group (NOVA is Scouting’s STEM program). I’m an assistant scoutmaster now and I think there are a few kids who might be interested. It’ll be winter before we can get the NOVA stuff off the ground, but meanwhile I’m planning.

I want the instrument package to do the following:

Experiments

  • Temp sensors combine with altitude measurements to record the adiabatic lapse rate. As altitude increases the temperature should drop 5 degrees per 1000 feet.
  • Audio sensors combined with altitude to demonstrate that in space, no one can hear you scream. As the altitude increases, air density decreases and sounds travel less effectively so the amplitude of an audio signal on a constant frequency should reduce.

Sensors

  • GPS (working; proven in my TrunkTrackerino project)
  • Temperature (working, both digital and analog)
  • Audio (working somewhat—need to learn to eliminate all but the test frequency, so the sensor only grabs that freq and determines its volume)

Package

I have the option of building on Raspberry Pi or Arduino. I’ve chosen to build on Arduino simply because that’s what I started with—the Pi being a full-fledged operating system is a bit more complex, but will be used for version 2. Pi offers a variety of great stuff, from a very small camera capable of video to a more powerful CPU. For now, I’d like to keep it simple. NOTE: I have three Pi version B’s, one of which could become the base package. The B+ was recently released, though, and seriously offers a better platform: more USB ports (4), lower power drain, etc. I may end up purchasing one of those.

Since the Arduino can’t do video, we’ll be sending up a GoPro camera. I have an older camera, purchased specifically for the balloon project.

So the total package will be:

  • Arduino Uno or Due (I have one of each)
  • Shield stack of GPS shield w/SD card + radio shield
  • {maybe} small hand-held to be used as a beacon
  • Temp sensors
  • Audio sensor (as yet unidentified)
  • Go-pro camera
  • Battery power for Arduino shield

Communications

As a licensed ham, I can use RF to transmit data back to earth. I want to transmit everything, in the worst-case chance that we don’t recover the instrument package. This means:

  • GPS coordinates: lat, long, altitude, trajectory, speed, rate of ascent/descent.
  • Temp/altitude pair
  • Temp/amplitude pair

I’d also like the package to switch to beacon mode, or to include a beacon, once the package descends to within 1000 feet of land, so we can more easily recover the package upon arrival.

There are the specs. Next step is to close on the communications package.

Balloon–Question, more questions…

I’ve mentioned a couple times on my blog that I’m interested in building a high-altitude balloon and sending some experiments up. I have worked for several years now on an Arduino-based package. I’ve successfully got GPS tracking working, SD cards, and a variety of sensors.

Now I’d like to take the next step and actually start transmitting sensor data over RF (preferably VHF or UHF). I see a lot of balloons going up with Trackuino-based comms, but I’ve also been intrigued with the Radio Shield 2 from Argent communications.

There are a ton of options—there are even folks sending photos back via radio layers. I haven’t found a really good primer yet for all the various options, but I’m getting started.

More to come…

Tuesday, August 12, 2014

SDR on Linux Mint

I picked up one of those "el-cheapo" SDR dongles off Amazon recently and got it working on Windows with SDR Sharp. I'm actually kind of happy with it - not enough time to do a lot, but it's a start. Of course, my Windows machine is my day-to-day work machine and SDR# uses a lot of resources. So why not move it to linux?

My Linux box runs Mint 17 (this will be important very soon). I poked around the Software Manager and was surprised that searching for "SDR" returned no results. I did a few interwebz searches and came across an excellent guide to using SDR on Linux--which included a full bash script for downloading and building GNU-Radio. Seeing that it *is* the workday, I figured that's probably better than doing it manually!

OOPS - when I tried to run the bash script, it alerted me that I need at least version 11 of Mint. But wait - like I said, I'm on Mint 17. I did a little troubleshooting by opening the script and found out the supported versions of Mint are hard-coded to 11, 12, 13, 14, and 15. So I did what any good hacker does and I simply added 17 to the list:


Bazinga! The script is now running.

In total, with me focusing on my business day, the script ran for about 5 hours (part of that was the script waiting for me to enter my password for "sudo" dependent actions).