Including the Ethernet lib, breaks my program.

I’m trying to build a project based on the project of Stephan King.
My goal is to make an http-request when I swipe a magnetic card through the reader.

I have the following code (from Stephan King), which prints the content on the magnetic card to the serial output. This works. But when I add the ethernet-library (by uncommenting the first line) it stops working…

I do need this ethernet library to build the http-functions… anyone any clue?

//#include <Ethernet.h>
/*
 * Magnetic Stripe Reader
 * by Stephan King http://www.kingsdesign.com
 *
 * Reads a magnetic stripe.
 *
 */
int cld1Pin = 5;            // Card status pin
int rdtPin = 2;             // Data pin
int reading = 0;            // Reading status
volatile int buffer[400];   // Buffer for data
volatile int i = 0;         // Buffer counter
volatile int bit = 0;       // global bit
char cardData[40];          // holds card info
int charCount = 0;          // counter for info
int DEBUG = 0;
 
void setup() {
  Serial.begin(9600); 
 
  // The interrupts are key to reliable
  // reading of the clock and data feed
  attachInterrupt(0, changeBit, CHANGE);
  attachInterrupt(1, writeBit, FALLING);
}
 
void loop(){
  // Active when card present
  while(digitalRead(cld1Pin) == LOW){
    reading = 1;
  }     
 
  // Active when read is complete
  // Reset the buffer
  if(reading == 1) {  
 
    if (DEBUG == 1) {
      printBuffer();
    }
 
    decode();
    reading = 0;
    i = 0;
 
    int l;
    for (l = 0; l < 40; l = l + 1) {
      cardData[l] = '\n';
    }
 
    charCount = 0;
  }
}
 
// Flips the global bit
void changeBit(){
  if (bit == 0) {
    bit = 1;
  } else {
    bit = 0;
  }
}
 
// Writes the bit to the buffer
void writeBit(){
  buffer[i] = bit;
  i++;
}
 
// prints the buffer
void printBuffer(){
  int j;
  for (j = 0; j < 200; j = j + 1) {
    Serial.println(buffer[j]);
  }
}
 
int getStartSentinal(){
  int j;
  int queue[5];
  int sentinal = 0;
 
  for (j = 0; j < 400; j = j + 1) {
    queue[4] = queue[3];
    queue[3] = queue[2];
    queue[2] = queue[1];
    queue[1] = queue[0];
    queue[0] = buffer[j];
 
    if (DEBUG == 1) {
      Serial.print(queue[0]);
      Serial.print(queue[1]);
      Serial.print(queue[2]);
      Serial.print(queue[3]);
      Serial.println(queue[4]);
    }
 
    if (queue[0] == 0 & queue[1] == 1 & queue[2] == 0 & queue[3] == 1 & queue[4] == 1) {
      sentinal = j - 4;
      break;
    }
  }
 
  if (DEBUG == 1) {
    Serial.print("sentinal:");
    Serial.println(sentinal);
    Serial.println("");
  }
 
  return sentinal;
}
 
void decode() {
  int sentinal = getStartSentinal();
  int j;
  int i = 0;
  int k = 0;
  int thisByte[5];
 
  for (j = sentinal; j < 400 - sentinal; j = j + 1) {
    thisByte[i] = buffer[j];
    i++;
    if (i % 5 == 0) {
      i = 0;
      if (thisByte[0] == 0 & thisByte[1] == 0 & thisByte[2] == 0 & thisByte[3] == 0 & thisByte[4] == 0) {
        break;
      }
      printMyByte(thisByte);
    }
  }
 
  Serial.print("Stripe_Data:");
  for (k = 0; k < charCount; k = k + 1) {
    Serial.print(cardData[k]);
  }
  Serial.println("");
 
}
 
void printMyByte(int thisByte[]) {
  int i;
  for (i = 0; i < 5; i = i + 1) {
    if (DEBUG == 1) {
      Serial.print(thisByte[i]);
    }
}
    if (DEBUG == 1) {
      Serial.print("\t");
      Serial.print(decodeByte(thisByte));
      Serial.println("");
    }
 
    cardData[charCount] = decodeByte(thisByte);
    charCount ++;
}
 
char decodeByte(int thisByte[]) {
    if (thisByte[0] == 0 & thisByte[1] == 0 & thisByte[2] == 0 & thisByte[3] == 0 & thisByte[4] == 1){
      return '0';
    }
    if (thisByte[0] == 1 & thisByte[1] == 0 & thisByte[2] == 0 & thisByte[3] == 0 & thisByte[4] == 0){
      return '1';
    }
 
    if (thisByte[0] == 0 & thisByte[1] == 1 & thisByte[2] == 0 & thisByte[3] == 0 & thisByte[4] == 0){
      return '2';
    }
 
    if (thisByte[0] == 1 & thisByte[1] == 1 & thisByte[2] == 0 & thisByte[3] == 0 & thisByte[4] == 1){
      return '3';
    }
 
    if (thisByte[0] == 0 & thisByte[1] == 0 & thisByte[2] == 1 & thisByte[3] == 0 & thisByte[4] == 0){
      return '4';
    }
 
    if (thisByte[0] == 1 & thisByte[1] == 0 & thisByte[2] == 1 & thisByte[3] == 0 & thisByte[4] == 1){
      return '5';
    }
 
    if (thisByte[0] == 0 & thisByte[1] == 1 & thisByte[2] == 1 & thisByte[3] == 0 & thisByte[4] == 1){
      return '6';
    }
 
    if (thisByte[0] == 1 & thisByte[1] == 1 & thisByte[2] == 1 & thisByte[3] == 0 & thisByte[4] == 0){
      return '7';
    }
 
    if (thisByte[0] == 0 & thisByte[1] == 0 & thisByte[2] == 0 & thisByte[3] == 1 & thisByte[4] == 0){
      return '8';
    }
 
    if (thisByte[0] == 1 & thisByte[1] == 0 & thisByte[2] == 0 & thisByte[3] == 1 & thisByte[4] == 1){
      return '9';
    }
 
    if (thisByte[0] == 0 & thisByte[1] == 1 & thisByte[2] == 0 & thisByte[3] == 1 & thisByte[4] == 1){
      return ':';
    }
 
    if (thisByte[0] == 1 & thisByte[1] == 1 & thisByte[2] == 0 & thisByte[3] == 1 & thisByte[4] == 0){
      return ';';
    }
 
    if (thisByte[0] == 0 & thisByte[1] == 0 & thisByte[2] == 1 & thisByte[3] == 1 & thisByte[4] == 1){
      return '<';
    }
 
    if (thisByte[0] == 1 & thisByte[1] == 0 & thisByte[2] == 1 & thisByte[3] == 1 & thisByte[4] == 0){
      return '=';
    }
 
    if (thisByte[0] == 0 & thisByte[1] == 1 & thisByte[2] == 1 & thisByte[3] == 1 & thisByte[4] == 0){
      return '>';
    }
 
    if (thisByte[0] == 1 & thisByte[1] == 1 & thisByte[2] == 1 & thisByte[3] == 1 & thisByte[4] == 1){
      return '?';
    }
}

volatile int buffer[400];

Well, there are 800 bytes gone in one array declaration. I'm surprised it worked before you included the ethernet library.

The ATmega328 has 2kb of RAM; other models of arduino have 1k - that's 1024 bytes - of RAM available to the program. ints are 2 bytes each, so this array takes 800 bytes. The serial buffer takes 128 more.

-j

Ok! I'm new to micro-processor programming, but do you maybe have an idea how I can solve this?

Thanks!

It looks like you’re using a 16 bit integer to store a single bit - 15/16ths of the space is wasted. Cut that in half by using a byte instead of an int (with no other changes to your code). This simple change may get you going.

Are there really 400 bits of data on a mag stripe card? If not, reduce.

I’d read enough bits to make a single character, store that character, and re-use the buffer for the next character. This way, you only need to store enough characters to fill up a card (as opposed to enough bits to full up a card).

If you are still tight on space, you can learn about bitwise manipulation, and store the incoming data directly to a byte. This won’t save significantly more space than that last suggestion, but it could allow some cool tricks to simplify writing/converting from the code on the card to an ASCII character (e.g. simplify you “if thisByte[...” code).

Worst case, you could probably read enough bits for a single character and transmit that lone character. I seriously doubt you will need to get that drastic.

-j

Memory is very tight on the arduino, this isn’t a PC. I learned this the hard way. Best to conserve whevever possible. I looked at your code and it appears that you are pulling in a series of 5 bit codes that are translated into an ascii character to hold your message data.

What I would do is have a single byte buffer that you use to store each 5 bit word as it comes in. You can shift the bit into the word each time one arrives and when you have five bits, decode it and store it in your cardData. Also, the decodeByte routine is very wasteful. You can do all of that with a lookup table, a 32 byte character array.

The code is below. You would need to add a routine that gets called when a message is complete that sends off your message and resets everything. THe only drawback to this is if you are limited in the amount of time to service the interrupt. I haven’t worked with interrutps on arduino, so i don’t know.

Also, you might want to minimize debug statements. Even though you need them, they take up space. Every character string takes up space. It’s not like on Unix where these get put into the program data. You can force these into program space using PROGMEM.

I wrote a program that reads temperature data, and posts this as an XML document. XML and HTML use lots of strings, so I had to stuff all strings into PROGMEM in order to get it to work.

BTW, I didn’t run this code, so it may not be 100%. The worst part about hitting the memory limit, is that weird things start to happen. Your code may be perfect, but it starts stepping on itself and things go wacky. Very frustrating.

Hope this helps.

joquer

volatile byte buffer = 0;
volatile byte cardData[80];

int nChars = 0;
int nBits = 0;

//
// Change that whole decode routine into a lookup Table.
//
static char lookupTable = {
‘0’, ‘1’, ‘2’, ‘3’, ‘4’, ‘5’, ‘6’, ‘7’, ‘8’, ‘9’, ‘;’
}

int writeBit()
{
if ( bit == 0 )
buffer = buffer << 1;
else
buffer = ( buffer << 1 ) || 1;
nBits++;
if ( nBits >= 5 )
{
cardData[nChars] = lookupTable[buffer];
nChars++;
buffer = 0;
nBits = 0;
}
}

Oops, I screwed up a rather important line, it should be a bitwise or not a logical or.

if ( bit == 0 )
buffer = buffer << 1;
else
buffer = ( buffer << 1 ) | 1;

Douwe Homans,

This looks like a interesting project.

How is it coming along so far?

Hi all,

Sorry for not replieing for a long time. I was very busy with my project and eventually it all worked out great! Joquer, thanks a lot for your info about memory! I didn't use your code, but your post really made me think about using as less memory as possible and it helped me out a lot!

I'm completely new to electonics and also to C and memory management, but have pretty much experience with php and delphi.

My goal was to create a box with a few buttons an lcd and a magnetic card reader which could connect via utp to a server. I needed this box as a 'cash-register' for a party.

It all worked out great. You could swipe a card(encoded with an unique number) and press one of the buttons (beer, coke, wine, etc..). It then connected to the server which kept track of how much money was on the card. The server decreased this amount with the price of the beer/coke/wine and send back to the arduino-box the new amount of money on the card. The box then displays this on its lcd screen.

At first my idea was to make a http requests to the server every time to tell it which button was pressed. But i tried and tested a lot, but still couldn't get it to work reliable. After a few button presses (and following http-requests) it stopped working.

I thought the problem could be in the fact that I created a new client object for every request. (I did also close it after I was done with it) But maybe some of them were not closed, or free'ed in memory correct?

Therefore I tried to do it more low-level. And not use the http protocol. I just let the arduino-box open a socket, and keep it open (not as with http). Over this socket I was able to send and receive data (from button presses, magnetic stripes, and responses from server to display on lcd) a whole night long, and that was what I needed for my party.

It was a great first project with electronics, and the party was a huge succes!