Arduinio Data Logger - Sketches
Functions for operating the uDrive by 4D Systems:
The data logger doesn't use most of the functions for RAW mode but they should work.
#include <NewSoftSerial.h>
#include <WString.h>
const int uDrive_AcknowledgementTimeout = 1000;
// const
#define ACK 0x06 // Acknowledge byte (means ok)
#define NACK 0x15 // Negative acknoledge byte (means not ok)
#define EXTENDED 0x40
#define DEVICE_INFO 0x56
#define INITIALIZE_MODULE 0x55
#define INITIALIZE_DISK 0x69
#define SET_ADDR 0x41
#define READ_BYTE 0x72
#define WRITE_BYTE 0x77
#define READ_SECTOR 0x52
#define WRITE_SECTOR 0x57
#define FAT_READ 0x61
#define FAT_WRITE 0x74
#define FAT_LIST 0x64
#define FAT_DELETE 0x65
#define APPEND_MODE_ON 0x80
#define APPEND_MODE_OFF 0x00
#define TX_PIN 9
#define RX_PIN 10
#define RESET_PIN 8
#define LED_PIN 13
NewSoftSerial uDrive_serial(TX_PIN, RX_PIN);
boolean uDrive_isIntitialized = false;
boolean uDrive_isDiskloaded = false;
unsigned long uDrive_sectorAddress = 1; // next sector to write
byte uDrive_buffer[0];
int uDrive_buffer_index = 0;
/*******************/
/* COMMON COMMANDS */
/*******************/
// Initialize uDrive
boolean uDrive_Initialize ()
{
// Reset device
pinMode (RESET_PIN, OUTPUT);
digitalWrite (RESET_PIN, LOW);
delay (10);
digitalWrite (RESET_PIN, HIGH);
delay (1000);
// Setup device
uDrive_serial.begin(9600); // 38400, 28800, 14400, 9600, 1200 or 300
uDrive_serial.print (INITIALIZE_MODULE, BYTE);
if (!uDrive_CheckAcknowledgement (5000))
{
return false;
}
// return
uDrive_isIntitialized = true;
return true;
}
// Load Disk
boolean uDrive_LoadDisk ()
{
uDrive_serial.print (EXTENDED, BYTE);
uDrive_serial.print (INITIALIZE_DISK, BYTE);
// check if successful
if (!uDrive_CheckAcknowledgement ())
return false;
// return
uDrive_isDiskloaded = true;
return true;
}
void uDrive_DeviceInfo()
{
uDrive_serial.print (DEVICE_INFO, BYTE);
for (int i=0; i < 5; i++)
{
while (!uDrive_serial.available())
{
delay (10);
}
int val = uDrive_serial.read();
Serial.println(val);
}
}
void uDrive_FatProtect(boolean on)
{
uDrive_serial.print (0x59, BYTE);
uDrive_serial.print (0x08, BYTE);
if (on)
uDrive_serial.print (0x01, BYTE);
else
uDrive_serial.print (0x00, BYTE);
WaitForAck();
}
// Check response if OK
boolean WaitForAck()
{
char b = 0;
while(b != ACK && b != NACK)
{
if(uDrive_serial.available() > 0)
{
b = uDrive_serial.read();
}
}
if(b == ACK)
{
return true;
}
return false;
}
boolean uDrive_CheckAcknowledgement ()
{
uDrive_CheckAcknowledgement (uDrive_AcknowledgementTimeout);
}
boolean uDrive_CheckAcknowledgement (int timeout)
{
// wait for ack
int iDelay = 10;
int i = 0;
while (!uDrive_serial.available())
{
delay (iDelay);
if (timeout / iDelay < i)
return false;
i += 1;
}
// Read
int val = uDrive_serial.read();
// Return
if (val != ACK)
{
return false;
}
return true;
}
void ClearJunk()
{
while(uDrive_serial.available() > 0)
{
char c = uDrive_serial.read();
}
}
void writeLong4(long data)
{
uDrive_serial.print (((data >> 24) & 0xff), BYTE); // Filesize
uDrive_serial.print (((data >> 16) & 0xff), BYTE);
uDrive_serial.print (((data >> 8) & 0xff), BYTE);
uDrive_serial.print (((data) & 0xff), BYTE);
}
void writeLong3(long data)
{
uDrive_serial.print (((data >> 16) & 0xff), BYTE);
uDrive_serial.print (((data >> 8) & 0xff), BYTE);
uDrive_serial.print (((data) & 0xff), BYTE);
}
/***********************/
/* RAW ACCESS COMMANDS */
/***********************/
boolean setAddress(long addr)
{
uDrive_serial.print (EXTENDED, BYTE);
uDrive_serial.print (SET_ADDR, BYTE);
writeLong4(addr);
// check if successful
if (uDrive_CheckAcknowledgement ())
{
return true;
}
else
{
return false;
}
}
boolean writeByte(byte b)
{
writeByte(b, -1);
}
boolean writeByte(byte b, long addr)
{
boolean addrOk = true;
if (addr >= 0)
{
addrOk = setAddress(addr);
}
if (addrOk)
{
uDrive_serial.print (EXTENDED, BYTE);
uDrive_serial.print (WRITE_BYTE, BYTE);
uDrive_serial.print (b, BYTE);
if (uDrive_CheckAcknowledgement ())
{
return true;
}
else
{
return false;
}
}
else
{
return false;
}
}
byte readByte()
{
readByte(-1);
}
byte readByte(long addr)
{
boolean addrOk = true;
if (addr >= 0)
{
addrOk = setAddress(addr);
}
if (addrOk)
{
uDrive_serial.print (EXTENDED, BYTE);
uDrive_serial.print (READ_BYTE, BYTE);
// wait for ack
int iDelay = 10;
int i = 0;
while (!uDrive_serial.available())
{
delay (iDelay);
if (uDrive_AcknowledgementTimeout / iDelay < i)
return false;
i += 1;
}
// Read
byte val = uDrive_serial.read();
return val;
}
else
{
return false;
}
}
void readSector(long addr)
{
uDrive_serial.print (EXTENDED, BYTE);
uDrive_serial.print (READ_SECTOR, BYTE);
writeLong3(addr);
int count = 0;
while (count < 512)
{
if (uDrive_serial.available() > 0)
{
uDrive_buffer[count] = uDrive_serial.read();
count ++;
}
else
{
delay(10);
}
}
}
boolean writeSector(long addr)
{
uDrive_serial.print (EXTENDED, BYTE);
uDrive_serial.print (WRITE_SECTOR, BYTE);
writeLong3(addr);
for (int i=0; i < 512; i++)
{
uDrive_serial.print(uDrive_buffer[i], BYTE);
}
if (uDrive_CheckAcknowledgement ())
{
return true;
}
else
{
return false;
}
}
boolean writeHeader()
{
for (int i=0; i < 512; i++)
{
uDrive_buffer[i] = 0;
}
uDrive_buffer[0] = ((uDrive_sectorAddress >> 16) & 0xff);
uDrive_buffer[1] = ((uDrive_sectorAddress >> 8) & 0xff);
uDrive_buffer[2] = ((uDrive_sectorAddress) & 0xff);
return writeSector(0);
}
void readHeader()
{
for (int i=0; i < 512; i++)
{
uDrive_buffer[i] = 0;
}
uDrive_buffer_index = 0;
readSector(0);
uDrive_sectorAddress = 0;
uDrive_sectorAddress = uDrive_sectorAddress | uDrive_buffer[0];
uDrive_sectorAddress = uDrive_sectorAddress << 8;
uDrive_sectorAddress = uDrive_sectorAddress | uDrive_buffer[1];
uDrive_sectorAddress = uDrive_sectorAddress << 8;
uDrive_sectorAddress = uDrive_sectorAddress | uDrive_buffer[2];
}
void clearDisk()
{
for (int i=0; i < 512; i++)
{
uDrive_buffer[i] = 0;
}
uDrive_buffer_index = 0;
uDrive_sectorAddress = 1;
writeHeader();
}
boolean writeSample(byte sample)
{
boolean result = true;
uDrive_buffer[uDrive_buffer_index] = sample;
if (uDrive_buffer_index == 511)
{
uDrive_buffer_index = 0;
result = writeSector(uDrive_sectorAddress);
if (result)
{
uDrive_sectorAddress++;
writeHeader();
}
}
else
{
uDrive_buffer_index++;
}
return result;
}
/***********************/
/* FAT ACCESS COMMANDS */
/***********************/
boolean uDrive_WriteFile(char *file, boolean overwrite, long numBytes, char *buff)
{
ClearJunk();
// command header
uDrive_serial.print(EXTENDED, BYTE);
uDrive_serial.print(FAT_WRITE, BYTE);
// handshaking, append
if(overwrite)
uDrive_serial.print(0x00 | APPEND_MODE_OFF, BYTE);
else
uDrive_serial.print(0x00 | APPEND_MODE_ON, BYTE);
for(int i = 0; i < strlen(file); i++)
{
uDrive_serial.print(file[i], BYTE);
}
uDrive_serial.print(0x00, BYTE);
// file size
writeLong4(numBytes+1);
// wait for ack
if (!WaitForAck())
{
return false;
}
for(int i = 0; i < numBytes; i++)
{
uDrive_serial.print(buff[i], BYTE);
}
uDrive_serial.print(0x0A, BYTE);
// wait for ack
if (!WaitForAck())
{
return false;
}
return true;
}
String uDrive_ListFiles()
{
ClearJunk();
// command header
uDrive_serial.print(EXTENDED, BYTE);
uDrive_serial.print(FAT_LIST, BYTE);
uDrive_serial.print("*.*");
uDrive_serial.print(0x00, BYTE);
int count = 0;
String inString = String(50);
while (count < 50)
{
if (uDrive_serial.available() > 0)
{
char c = uDrive_serial.read();
if (c == ACK)
{
break;
}
else
{
inString.append(c);
count++;
}
}
else
{
delay(10);
}
}
return inString;
}
boolean uDrive_EraseFile(char *file)
{
ClearJunk();
// command header
uDrive_serial.print(EXTENDED, BYTE);
uDrive_serial.print(FAT_DELETE, BYTE);
for(int i = 0; i < strlen(file); i++)
{
uDrive_serial.print(file[i], BYTE);
}
uDrive_serial.print(0x00, BYTE);
// wait for ack
if (!WaitForAck())
{
return false;
}
return true;
}
int uDrive_ReadInt()
{
int iDelay = 10;
int i = 0;
while (!uDrive_serial.available())
{
delay (iDelay);
if (uDrive_AcknowledgementTimeout / iDelay < i)
return false;
i += 1;
}
// Read
int val = uDrive_serial.read();
return val;
}
char uDrive_ReadChar()
{
int iDelay = 10;
int i = 0;
while (!uDrive_serial.available())
{
delay (iDelay);
if (uDrive_AcknowledgementTimeout / iDelay < i)
return false;
i += 1;
}
// Read
char val = uDrive_serial.read();
return val;
}
boolean uDrive_ReadFile(char *file)
{
ClearJunk();
// command header
uDrive_serial.print(EXTENDED, BYTE);
uDrive_serial.print(FAT_READ, BYTE);
uDrive_serial.print(0x32, BYTE);
for(int i = 0; i < strlen(file); i++)
{
uDrive_serial.print(file[i], BYTE);
}
uDrive_serial.print(0x00, BYTE);
long size = 0;
long data = 0;
data = uDrive_ReadInt();
size = size | (data << 24);
data = uDrive_ReadInt();
size = size | (data << 16);
data = uDrive_ReadInt();
size = size | (data << 8);
data = uDrive_ReadInt();
size = size | (data);
uDrive_serial.print(ACK, BYTE);
String inString = String(50);
char count = 0;
for(int i = 0; i < size; i++)
{
char c = uDrive_ReadChar();
inString.append(c);
// handshake
if(count == 49)
{
Serial.print(inString);
inString.clear();
count = 0;
uDrive_serial.print(ACK, BYTE);
}
else
{
count++;
}
}
Serial.print(inString);
// wait for ack
if (!WaitForAck())
{
return false;
}
return true;
}
int uDrive_FileSize(char *file)
{
ClearJunk();
// command header
uDrive_serial.print(EXTENDED, BYTE);
uDrive_serial.print(FAT_READ, BYTE);
uDrive_serial.print(0x32, BYTE);
for(int i = 0; i < strlen(file); i++)
{
uDrive_serial.print(file[i], BYTE);
}
uDrive_serial.print(0x00, BYTE);
long size = 0;
long data = 0;
data = uDrive_ReadInt();
size = size | (data << 24);
data = uDrive_ReadInt();
size = size | (data << 16);
data = uDrive_ReadInt();
size = size | (data << 8);
data = uDrive_ReadInt();
size = size | (data);
uDrive_serial.print(NACK, BYTE);
return size;
}
This is the main data logger code:
/* Arduino sketch for Inspeed Vortex windspeed instrument
The anemometer.
=========================================================
ANEMOMETER
=========================================================
This is connected to Arduino ground on one side, and pin 2 (for the
attachInterrupt(0, ...) on the other.
Pin 2 is pulled up, and the reed switch on the anemometer will send
that to ground once per revolution, which will trigger the interrupt.
We count the number of revolutions in 5 seconds, and divide by 5.
One Hz (rev/sec) = 2.5 mph.
*********************************************************************/
#include <LiquidCrystal.h>
#include<stdlib.h>
#define uint unsigned int
#define ulong unsigned long
#define DEBUG_MODE false
#define SERIAL_MODE true
#define PIN_ANEMOMETER 2 // Digital 2
// How often we want to calculate wind speed (msec)
#define MSECS_CALC_WIND_SPEED 10000.0 // 10 sec
#define AVG_SPEED_MULTIPLIER 30.0 // 5 min
volatile int numRevsAnemometer = 0; // Incremented in the interrupt
float avgSpeedTotal = 0;
ulong nextCalcSpeed; // When we next calc the wind speed
ulong nextAvgCalcSpeed; // When we next calc the average wind speed
ulong time; // Millis() at each start of loop().
unsigned writeCount = 0;
LiquidCrystal lcd(12, 11, 6, 5, 4, 3);
void setup()
{
// LED (2 * blink)
pinMode(LED_PIN, OUTPUT);
digitalWrite(LED_PIN, HIGH);
delay(200);
digitalWrite(LED_PIN, LOW);
delay(200);
digitalWrite(LED_PIN, HIGH);
pinMode(PIN_ANEMOMETER, INPUT);
digitalWrite(PIN_ANEMOMETER, HIGH);
attachInterrupt(0, countAnemometer, FALLING);
nextCalcSpeed = millis() + MSECS_CALC_WIND_SPEED;
nextAvgCalcSpeed = millis() + (MSECS_CALC_WIND_SPEED * AVG_SPEED_MULTIPLIER);
// set up the LCD's number of rows and columns:
lcd.begin(16, 2);
// Print a message to the LCD.
lcd.clear();
lcd.print("Setup begin");
// Serial
if ((DEBUG_MODE) || (SERIAL_MODE))
{
Serial.begin(9600);
Console ("Setup begin");
}
// Initialize uDrive
if (!uDrive_Initialize ())
{
Console ("Device not initialized");
lcd.clear();
lcd.print("Device not initialized");
}
// Check if Disk is inserted
if (!uDrive_LoadDisk())
{
Console ("Disk not loaded");
lcd.clear();
lcd.print("Disk not loaded");
}
char buffer[] = "START";
uDrive_WriteFile("SPEED.TXT", false, strlen(buffer), buffer);
lcd.clear();
lcd.print("Setup done");
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Spd:");
lcd.setCursor(0,1);
lcd.print("Avg:");
}
void Console(char *text)
{
if (DEBUG_MODE)
{
Serial.println(text);
}
}
//=======================================================
// Calculate the wind speed
// 1 rev/sec = 2.5 mph
//=======================================================
void calcWindSpeed2()
{
writeCount++;
char buffer[6];
float seconds = MSECS_CALC_WIND_SPEED / 1000.0;
float revsPerSecond = (float)numRevsAnemometer / seconds;
float fspeed = revsPerSecond * 2.5;
Console("Speed:");
Console(dtostrf(fspeed,4,1,buffer));
dtostrf(fspeed,4,1,buffer);
lcd.setCursor(5,0);
lcd.print(buffer);
avgSpeedTotal += fspeed;
if (time > nextAvgCalcSpeed)
{
float aspeed = avgSpeedTotal / AVG_SPEED_MULTIPLIER;
avgSpeedTotal = 0;
char abuffer[6];
dtostrf(aspeed,4,1,abuffer);
lcd.setCursor(5,1);
lcd.print(abuffer);
nextAvgCalcSpeed = time + (MSECS_CALC_WIND_SPEED * AVG_SPEED_MULTIPLIER);
}
//writeSample(numRevsAnemometer);
if (uDrive_WriteFile("SPEED.TXT", false, strlen(buffer), buffer))
{
Console("Write OK");
lcd.setCursor(15,1);
lcd.print("*");
}
else
{
Console("Write Failed");
lcd.setCursor(15,1);
lcd.print("e");
}
lcd.setCursor(10,0);
char count[11];
sprintf(count, "%06d", writeCount);
lcd.print(count);
numRevsAnemometer = 0; // Reset counter
}
//=======================================================
// Interrupt handler for anemometer. Called each time the reed
// switch triggers (one revolution).
//=======================================================
void countAnemometer()
{
numRevsAnemometer++;
}
//=======================================================
// Main loop.
//=======================================================
void loop()
{
boolean paused = false;
if (SERIAL_MODE)
{
int incomingByte = 0;
if (Serial.available() > 0)
{
incomingByte = Serial.read();
if ((incomingByte == 76) || (incomingByte==108)) // L
{
String list = uDrive_ListFiles();
Serial.println("Files:");
Serial.println(list);
}
else if ((incomingByte == 115) || (incomingByte==83)) // S - Start Writing
{
numRevsAnemometer = 0;
nextCalcSpeed = millis() + MSECS_CALC_WIND_SPEED;
nextAvgCalcSpeed = millis() + (MSECS_CALC_WIND_SPEED * AVG_SPEED_MULTIPLIER);
paused = false;
lcd.setCursor(15,1);
lcd.print(" ");
Serial.println("Data logging started.");
}
else if ((incomingByte == 112) || (incomingByte==80)) // P - Pause Writing
{
paused = true;
lcd.setCursor(15,1);
lcd.print("P");
Serial.println("Data logging paused.");
}
else if ((incomingByte == 100) || (incomingByte==68)) // D - Delete File
{
if (uDrive_EraseFile("SPEED.TXT"))
{
Serial.println("File deleted successfully");
writeCount = 0;
}
else
{
Serial.println("Error deleting file");
}
}
else if ((incomingByte == 114) || (incomingByte==82)) // R - Read File
{
uDrive_ReadFile("SPEED.TXT");
}
else if ((incomingByte == 70) || (incomingByte==102)) // F - Read File Size
{
Serial.print("File Size: ");
Serial.println(uDrive_FileSize("SPEED.TXT"));
}
else if ((incomingByte == 77) || (incomingByte==109)) // M - Show Menu
{
Serial.println("M - Show this menu");
Serial.println("L - List files");
Serial.println("P - Pause file writing");
Serial.println("S - Start file writing");
Serial.println("R - Read file");
Serial.println("D - Delete file");
Serial.println("F - Show file size");
}
}
}
if (!paused)
{
time = millis();
if (time >= nextCalcSpeed)
{
calcWindSpeed2();
nextCalcSpeed = time + MSECS_CALC_WIND_SPEED;
}
}
}