|
@@ -1,26 +1,50 @@
|
|
|
#include <SPI.h>
|
|
|
#include <TimerOne.h>
|
|
|
+#include <digitalWriteFast.h>
|
|
|
|
|
|
#define FASTADC 1
|
|
|
|
|
|
+#define CHANNELS 3 /* possible values: 1, 3, 7 */
|
|
|
+
|
|
|
#define ETHERNET 1
|
|
|
#define SDCARD 2
|
|
|
+#define STORETO ETHERNET
|
|
|
+//#define STORETO SDCARD
|
|
|
|
|
|
-//#define STORETO ETHERNET
|
|
|
-#define STORETO SDCARD
|
|
|
-
|
|
|
+#define HAVE_LEDS
|
|
|
+//#define LOCKS
|
|
|
+#define DEBUG
|
|
|
|
|
|
#if STORETO == ETHERNET
|
|
|
#include <EthernetV2_0.h>
|
|
|
//#define UDP_BUFSIZE UDP_TX_PACKET_MAX_SIZE
|
|
|
-#define UDP_BUFSIZE 800
|
|
|
+#define UDP_BUFSIZE 768
|
|
|
+
|
|
|
+#define STORAGE_LATENCY 25
|
|
|
+
|
|
|
+#define BUFSIZE UDP_BUFSIZE
|
|
|
+
|
|
|
#endif
|
|
|
#if STORETO == SDCARD
|
|
|
-#include <SD.h>
|
|
|
+#include <SdFat.h>
|
|
|
+#include <SdFatUtil.h>
|
|
|
+Sd2Card sdCard;
|
|
|
+
|
|
|
+#define SD_BLOCKSIZE 512
|
|
|
+#define SD_BUFSIZE (SD_BLOCKSIZE + 512)
|
|
|
+#define SD_HEADERS "\000voltlogger\000\001\000\000\000VoltloggerA0000\0000"
|
|
|
+
|
|
|
+#define STORAGE_LATENCY 25
|
|
|
+
|
|
|
+#define BUFSIZE SD_BUFSIZE
|
|
|
+
|
|
|
+uint32_t sdWriteBlockAddress;
|
|
|
+uint32_t sdCardSizeBlocks;
|
|
|
+#endif
|
|
|
|
|
|
-//#define DUMPFILENAME "voltloggera0000-dump.txt"
|
|
|
-#define DUMPFILENAME "datalog.txt"
|
|
|
-#define SD_BUFSIZE 512
|
|
|
+#ifdef LOCKS
|
|
|
+volatile uint8_t WriteBufferLock_loop = 0;
|
|
|
+volatile uint8_t WriteBufferLock_pushValue = 0;
|
|
|
#endif
|
|
|
|
|
|
|
|
@@ -82,33 +106,65 @@ void resetFunc() {
|
|
|
void (*resetFunc)(void) = 0;
|
|
|
|
|
|
|
|
|
-#if STORETO == ETHERNET
|
|
|
-unsigned char WriteBuffer[UDP_BUFSIZE];
|
|
|
-#endif
|
|
|
-#if STORETO == SDCARD
|
|
|
-unsigned char WriteBuffer[SD_BUFSIZE];
|
|
|
-#endif
|
|
|
-int WriteBufferFilled;
|
|
|
+unsigned char WriteBuffer[BUFSIZE];
|
|
|
+
|
|
|
+volatile uint16_t WriteBufferFilled;
|
|
|
|
|
|
void pushValue()
|
|
|
{
|
|
|
- if (WriteBufferFilled >= sizeof(WriteBuffer) - 3) {
|
|
|
+ if (WriteBufferFilled >= BUFSIZE - (1+CHANNELS)*2) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
+#ifdef LOCKS
|
|
|
+ WriteBufferLock_pushValue = 1;
|
|
|
+ if (WriteBufferLock_loop) {
|
|
|
+ WriteBufferLock_pushValue = 0;
|
|
|
+ return;
|
|
|
+ }
|
|
|
+#endif
|
|
|
+
|
|
|
+ //volatile uint16_t newWriteBufferFilled = WriteBufferFilled;
|
|
|
uint16_t value;
|
|
|
uint16_t timestamp;
|
|
|
- value = analogRead(5);
|
|
|
timestamp = micros();
|
|
|
WriteBuffer[WriteBufferFilled++] = timestamp;
|
|
|
WriteBuffer[WriteBufferFilled++] = timestamp >> 8;
|
|
|
- WriteBuffer[WriteBufferFilled++] = value;
|
|
|
- WriteBuffer[WriteBufferFilled++] = value >> 8;
|
|
|
+
|
|
|
+ uint8_t chan = 0;
|
|
|
+ while (chan < CHANNELS) {
|
|
|
+ value = analogRead(chan++);
|
|
|
+ WriteBuffer[WriteBufferFilled++] = value;
|
|
|
+ WriteBuffer[WriteBufferFilled++] = value >> 8;
|
|
|
+ }
|
|
|
+ //WriteBufferFilled = newWriteBufferFilled;
|
|
|
+#ifdef LOCKS
|
|
|
+ WriteBufferLock_pushValue = 0;
|
|
|
+#endif
|
|
|
+ //Serial.println(WriteBufferFilled);
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+/* ========= */
|
|
|
+
|
|
|
+void stateWarning() {
|
|
|
+#ifdef HAVE_LEDS
|
|
|
+ digitalWrite(LED_GREEN, LOW);
|
|
|
+ delay(250);
|
|
|
+ digitalWrite(LED_GREEN, HIGH);
|
|
|
+ delay(250);
|
|
|
+ digitalWrite(LED_GREEN, LOW);
|
|
|
+ delay(250);
|
|
|
+ digitalWrite(LED_GREEN, HIGH);
|
|
|
+#endif
|
|
|
+ delay(250);
|
|
|
+ return;
|
|
|
}
|
|
|
|
|
|
+
|
|
|
void setup()
|
|
|
{
|
|
|
- Serial.begin(9600);
|
|
|
+ Serial.begin(115200);
|
|
|
#ifdef WAIT_FOR_SERIAL
|
|
|
while (!Serial) {
|
|
|
; // wait for serial port to connect. Needed for Leonardo only
|
|
@@ -116,26 +172,31 @@ void setup()
|
|
|
#endif
|
|
|
Serial.println("Welcome to VoltloggerA0000!\n");
|
|
|
Serial.println("Starting initialization...");
|
|
|
-/*
|
|
|
+
|
|
|
+#ifdef HAVE_LEDS
|
|
|
pinMode(LED_GREEN, OUTPUT);
|
|
|
digitalWrite(LED_GREEN, HIGH);
|
|
|
pinMode(LED_RED, OUTPUT);
|
|
|
digitalWrite(LED_RED, HIGH);
|
|
|
-*/
|
|
|
- SPI.setClockDivider(SPI_CLOCK_DIV2);
|
|
|
+#endif
|
|
|
+
|
|
|
#if FASTADC
|
|
|
sbi(ADCSRA, ADPS2);
|
|
|
cbi(ADCSRA, ADPS1);
|
|
|
cbi(ADCSRA, ADPS0);
|
|
|
#endif
|
|
|
-
|
|
|
+ SPI.setClockDivider(SPI_CLOCK_DIV2);
|
|
|
#if STORETO == ETHERNET
|
|
|
+
|
|
|
+
|
|
|
pinMode(SDCARD_CS, OUTPUT);
|
|
|
digitalWrite(SDCARD_CS, HIGH); // disable SD card if one in the slot
|
|
|
#endif
|
|
|
#if STORETO == SDCARD
|
|
|
pinMode(W5200_CS, OUTPUT);
|
|
|
+ digitalWrite(W5200_CS, HIGH); // disable W5200
|
|
|
#endif
|
|
|
+
|
|
|
pinMode(SS, OUTPUT);
|
|
|
pinMode(nRST, OUTPUT);
|
|
|
pinMode(nPWDN, OUTPUT);
|
|
@@ -151,6 +212,7 @@ void setup()
|
|
|
|
|
|
while(!Ethernet.begin(mac)) {
|
|
|
Serial.println("Retring DHCP...");
|
|
|
+ stateWarning();
|
|
|
}
|
|
|
|
|
|
Serial.print("Local address: ");
|
|
@@ -158,7 +220,7 @@ void setup()
|
|
|
Serial.print(":");
|
|
|
Serial.println(port_local);
|
|
|
ip_remote = Ethernet.localIP();
|
|
|
- ip_remote[3] = 2;
|
|
|
+ ip_remote[3] = 3;
|
|
|
Serial.print("Remote address: ");
|
|
|
Serial.print(ip_remote);
|
|
|
Serial.print(":");
|
|
@@ -169,54 +231,47 @@ void setup()
|
|
|
|
|
|
#if STORETO == SDCARD
|
|
|
Serial.println("Initializing SD card...");
|
|
|
-
|
|
|
- // see if the card is present and can be initialized:
|
|
|
- while (!SD.begin(SDCARD_CS)) {
|
|
|
- Serial.println("Card failed, or not present! Retrying...");
|
|
|
- digitalWrite(LED_GREEN, LOW);
|
|
|
- delay(250);
|
|
|
- digitalWrite(LED_GREEN, HIGH);
|
|
|
- delay(250);
|
|
|
- digitalWrite(LED_GREEN, LOW);
|
|
|
- delay(250);
|
|
|
- digitalWrite(LED_GREEN, HIGH);
|
|
|
- delay(250);
|
|
|
- }
|
|
|
- Serial.println("The card is initialized");
|
|
|
-
|
|
|
- Serial.println("Trying to open file \""DUMPFILENAME"\" for writting...");
|
|
|
- sddumpfile = SD.open(DUMPFILENAME, FILE_WRITE);
|
|
|
- if (!sddumpfile) {
|
|
|
- Serial.println("Error: Cannot open file \""DUMPFILENAME"\" for writting!");
|
|
|
- //digitalWrite(LED_GREEN, LOW);
|
|
|
- delay(1000);
|
|
|
- resetFunc();
|
|
|
+
|
|
|
+ while (!sdCard.begin(SDCARD_CS, SPI_FULL_SPEED)) {
|
|
|
+ Serial.println("Error: Initialization of the SD card failed or it doesn't present! Retrying...");
|
|
|
+ stateWarning();
|
|
|
}
|
|
|
-
|
|
|
+ sdCardSizeBlocks = sdCard.cardSize();
|
|
|
+ memset(WriteBuffer, 0, SD_BLOCKSIZE);
|
|
|
+ memcpy(WriteBuffer, SD_HEADERS, sizeof(SD_HEADERS));
|
|
|
+ WriteBuffer[13] = CHANNELS;
|
|
|
+ sdCard.writeBlock(0, WriteBuffer);
|
|
|
+ sdWriteBlockAddress = 1;
|
|
|
+ Serial.print("The SD card is initialized. Availiable block-count (512 bytes): ");
|
|
|
+ Serial.println(sdCardSizeBlocks);
|
|
|
#endif
|
|
|
|
|
|
WriteBufferFilled = 0;
|
|
|
- //Timer1.initialize(50);
|
|
|
- //Timer1.attachInterrupt(pushValue);
|
|
|
- //digitalWrite(LED_RED, LOW);
|
|
|
+ Timer1.initialize(STORAGE_LATENCY * (1 + CHANNELS));
|
|
|
+ Timer1.attachInterrupt(pushValue);
|
|
|
+#ifdef HAVE_LEDS
|
|
|
+ digitalWrite(LED_RED, LOW);
|
|
|
+ //digitalWrite(LED_GREEN, LOW);
|
|
|
+#endif
|
|
|
Serial.println("Initialization complete.");
|
|
|
|
|
|
}
|
|
|
|
|
|
-#define BYTES_PER_PACKET (UDP_BUFSIZE << 2)
|
|
|
|
|
|
+/* ========= */
|
|
|
+
|
|
|
+//uint16_t count = 0;
|
|
|
void loop()
|
|
|
{
|
|
|
|
|
|
- int oldWriteBufferFilled;
|
|
|
- int newWriteBufferFilled;
|
|
|
+ volatile uint16_t oldWriteBufferFilled;
|
|
|
|
|
|
#if STORETO == ETHERNET
|
|
|
udp.beginPacket(ip_remote, port_remote);
|
|
|
|
|
|
oldWriteBufferFilled = WriteBufferFilled;
|
|
|
udp.write(WriteBuffer, WriteBufferFilled);
|
|
|
- newWriteBufferFilled = WriteBufferFilled;
|
|
|
+ int newWriteBufferFilled = WriteBufferFilled;
|
|
|
WriteBufferFilled = 0;
|
|
|
|
|
|
if (oldWriteBufferFilled != newWriteBufferFilled) {
|
|
@@ -226,19 +281,55 @@ void loop()
|
|
|
udp.endPacket();
|
|
|
#endif
|
|
|
#if STORETO == SDCARD
|
|
|
- Serial.print("Writting ");
|
|
|
- Serial.print(WriteBufferFilled);
|
|
|
- Serial.println(" bytes to the SD card");
|
|
|
- while (WriteBufferFilled < );
|
|
|
+/*
|
|
|
+ count++;
|
|
|
+ if (count >> 8 != 0) {
|
|
|
+ Serial.println(count);
|
|
|
+ count = 0;
|
|
|
+ }*/
|
|
|
+
|
|
|
+ //Serial.println("Waiting for data...");
|
|
|
+ if (WriteBufferFilled < SD_BLOCKSIZE) {
|
|
|
+ //pushValue();
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ //Serial.println("Writting the data...");
|
|
|
oldWriteBufferFilled = WriteBufferFilled;
|
|
|
- if (sddumpfile.write(WriteBuffer, WriteBufferFilled) != WriteBufferFilled) {
|
|
|
- Serial.println("problem");
|
|
|
+ sdCard.writeBlock(sdWriteBlockAddress++, WriteBuffer);
|
|
|
+#ifdef LOCKS
|
|
|
+ WriteBufferLock_loop = 1;
|
|
|
+ while(WriteBufferLock_pushValue);
|
|
|
+#endif
|
|
|
+ volatile uint16_t leftLen = WriteBufferFilled - oldWriteBufferFilled;
|
|
|
+
|
|
|
+ WriteBufferFilled = leftLen;
|
|
|
+
|
|
|
+ if (leftLen > 0) {
|
|
|
+#ifdef DEBUG
|
|
|
+ if (leftLen == 512) {
|
|
|
+ Serial.println("Overflow.");
|
|
|
+ }
|
|
|
+#endif
|
|
|
+ memcpy(WriteBuffer, &WriteBuffer[SD_BLOCKSIZE], leftLen);
|
|
|
}
|
|
|
- newWriteBufferFilled = WriteBufferFilled;
|
|
|
- WriteBufferFilled = 0;
|
|
|
-
|
|
|
- if (oldWriteBufferFilled != newWriteBufferFilled) {
|
|
|
- //sddumpfile.write(&WriteBuffer[oldWriteBufferFilled], newWriteBufferFilled - oldWriteBufferFilled);
|
|
|
+#ifdef DEBUG
|
|
|
+ else {
|
|
|
+ Serial.println("No data queued");
|
|
|
+ }
|
|
|
+#endif
|
|
|
+#ifdef LOCKS
|
|
|
+ WriteBufferLock_loop = 0;
|
|
|
+#endif
|
|
|
+ while (sdWriteBlockAddress >= sdCardSizeBlocks) {
|
|
|
+ Serial.println("SD card is full...");
|
|
|
+#ifdef HAVE_LEDS
|
|
|
+ digitalWrite(LED_RED, LOW);
|
|
|
+ digitalWrite(LED_GREEN, HIGH);
|
|
|
+ delay(500);
|
|
|
+ digitalWrite(LED_RED, LOW);
|
|
|
+ digitalWrite(LED_GREEN, HIGH);
|
|
|
+#endif
|
|
|
+ delay(500);
|
|
|
}
|
|
|
#endif
|
|
|
}
|