My cheap solar logger (TinyFAT/Sram problem)

I Hope you guys can help me.

I’m working on a cheap solar logger (10-20$) that counts pulses from a kWh meter.

The basic functions are:

  • Read pulses from the kWh meter
  • Log these pulses into a CSV

The advanced functiontionalities are:

  • Logging temperature sensors
  • Managing the inverter temperature according to the temp sensors
  • Transmitting results over RF

I was using the default SD.h library but after the project grew it started to fail on me (not enough SRAM). So I switched to TinyFAT since it was much less SRAM hungry

I’m just having problems getting TinyFAT to work. It always returns an error (ERROR_MBR_SIGNATURE). I’m using a 2GB SD card formated with SDformatter. If i use the examples that come with TinyFAT everything works but when I use my own project I’m unable to complete the setup.

Small remark: I’ve been running the examples on a Arduino UNO. My project uses a Stand alone Atmega328 on a breadboard.

This is the schematic:

My question(s):

  • Why won’t TinyFAT start?
  • Any tips on reducing the SRAM usage?
  • If you any other questionable coding please let me know.

I attached the full .ino to this post.

This is the setup part:

ERROR CODES:
============
# blinks     Error
1            SD card failed, or not present
2            Reading time failed
3            Unable to write to file
4            Error while Sending RF (message too long)
5            Error reading file from SD for daily result
6            SD Error reading MBR
7            SD MBR Signature error
8            SD Unsupported filesystem
9            SD Error reading Boot Sector
10           SD Boot Sector Signature error
11           SD Unknown error
*/


#include <DS3231.h>
#include <Wire.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include <MemoryFree.h>
#include <VirtualWire.h>
#include <tinyFAT.h>
#include <avr/pgmspace.h>

//Pin settings
//SD
const byte chipSelectPin = 10;
//LEDs
const byte errorLedPin = 4;
const byte confirmLedPin = 5;
//RF module
const byte rfPin = 6;
//Fan Switching
const byte fanPin = 3;
//Interrupt Variables
const byte interruptPinS0 = 2;
//Daily results button
const byte dailyResultsButton = 8;

//Settings
//DS3231 variables
DS3231 Clock;
byte Year, Month, Date, DoW, Hour, Minute, Second;
//Confirm led variables
const byte confirmLedInterval = 50;
const byte errorLedInterval = 250;
volatile byte confirmLedBlinks = 0;
byte confirmLedState = LOW;
unsigned long confirmLedPreviousMillis = 0;
//Interrupt Variables
const byte minimumInteruptDifference = 200;
volatile unsigned long previousInterruptMillis = 0;
volatile unsigned int S0Counter = 0;
volatile unsigned int DailyProd = 0;
volatile boolean broadcastPulse = false;
//Temperatures variables
#define ONE_WIRE_BUS 7
#define TEMPERATURE_PRECISION 12
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
float temp1, temp2, temp3;
boolean getTemps = true;
//Fan variables
const byte fanStartTemp = 25;
const byte fanMaxTemp = 30;
const byte fanMinSpeed = 100;
byte fanCurrentSpeedPCT  = 0;
//Log variables
byte bytLogIntervalMinutes = 5;
byte maxlogsWithZeroPulses = 5;
const char chrSeparator = ';';
//CSV character
byte bytLastLogMinute = 0;
byte logsWithZeroPulses = 100;
//Power variables
const long millisinHour = 3600000;
volatile unsigned int currentPower = 0;
//SD variables
byte res; 
int verboseError(byte err)
{
  switch (err)
  {
  case ERROR_MBR_READ_ERROR:
    return 6;
    break;
  case ERROR_MBR_SIGNATURE:
    return 7;
    break;
  case ERROR_MBR_INVALID_FS:
    return 8;
    break;
  case ERROR_BOOTSEC_READ_ERROR:
    return 9;
    break;
  case ERROR_BOOTSEC_SIGNATURE:
    return 10;
    break;
  default:
    return 11;
    break;
  }
}

void setup()
{

  //Set pinmodes
  pinMode(errorLedPin,OUTPUT);  
  pinMode(confirmLedPin,OUTPUT);  
  pinMode(chipSelectPin, OUTPUT);
  pinMode(fanPin, OUTPUT);
  pinMode(interruptPinS0, INPUT);
  pinMode(rfPin,OUTPUT);
  pinMode(dailyResultsButton,INPUT);

  //RF module
  vw_set_tx_pin(rfPin);
  vw_set_ptt_inverted(true);
  vw_setup(2000);
  printMemoryUsage();

  //Start wire for DS3221
  Wire.begin();

  //DS18B20
  sensors.begin();
  getNewTemps();

  // Start SD
  file.setSSpin(chipSelectPin);
  byte res=file.initFAT(SPISPEED_MEDIUM); 
  if (res!=NO_ERROR)
  {
    errorLoop(verboseError(res), false);
  }

  //Attach interupt to interupt pin 0 = pin 2 on the arduino
  attachInterrupt(0, S0interrupt, FALLING);

  //High Frequency pwm on pin 3 and 11 (only 3 is used)
  TCCR2B = TCCR2B & 0b11111000 | 0x01;

  confirmLedBlinks++;  
  printMemoryUsage();
}

Solarlogger_2013_08_18.ino (14.2 KB)

Perhaps you want to see this great project.
http://openenergymonitor.org/emon/

Such an project requires an Arduino Mega 2560 board.

HugoPT:
Perhaps you want to see this great project.
http://openenergymonitor.org/emon/

I’ve seen the Emon.

  • But it will cost much more
  • It doesn’t log to SD
  • Creating and understanding it yourself is much more fun.

Erdin:
Such an project requires an Arduino Mega 2560 board.

Why should i need a Mega 2560? I’m only using 24kb out of 32kb prog mem and i’m using 1.4kb out of 2kb Sram…
The atmega328 itself should be fast enough to handle this task.

If i use the examples that come with TinyFAT everything works but when I use my own project I'm unable to complete the setup.

I'm not familiar with that library, but if it isn't working then I suppose it must be because you're using the API incorrectly, or the library conflicts with something else that is happening in your sketch.

Perhaps you could write a test sketch based on your main sketch with everything removed except the code directly relating to the SD card, and see whether you get the same problem. If you do, it suggests you're using the API wrongly and you could compare that to the working examples to see if you can see why. If not, something else you're doing must be causing a conflict and you could gradually reinstate the other functions until you encounter the problem. From there you could go on to narrow down the precise source of the conflict.

The Arduino Mega 2560 is just as fast. It has larger memory, so you could use the normal SD library again.
You don't seem to need large arrays in your sketch, so perhaps the normal SD library with your board is possible, with a little tweaking.

What is the MemoryFree library ? Does it use ram memory ?
The OneWire and DallasTemperature libraries contain many extras. With just one DS18B20, a lot of that code is not needed.
You don't need the DallasTemperature library at all. You could use the example code that came with the OneWire library.
Which DS3231 library is that ? Are there options inside to disable parts of the code ?
The VirtualWire has buffers, you can change those, but it will only be a few bytes.

Erdin:
The Arduino Mega 2560 is just as fast. It has larger memory, so you could use the normal SD library again.
You don't seem to need large arrays in your sketch, so perhaps the normal SD library with your board is possible, with a little tweaking.

I know but it won't be as easy to create a stand alone on a perf board.

What is the MemoryFree library ? Does it use ram memory ?

It is used to measure the SRAm usage

The OneWire and DallasTemperature libraries contain many extras. With just one DS18B20, a lot of that code is not needed.
You don't need the DallasTemperature library at all. You could use the example code that came with the OneWire library.
Which DS3231 library is that ? Are there options inside to disable parts of the code ?

I'm using 3 temp sensors.

I'll be going at it as PeterH suggested rebuilding the project and see when it starts locking up...