Proof of concept

Hi everyone!

I'm new to the forum, as well as the world of Arduinos and programming (though I have some very limited experience with the latter).

I'm from Hungary, and recently, there has been a scandal in the media about how the government public transport company spent tens of millions of forints to research the feasibility of an RFID pass system, as well as developing the systemwith no results after a year, despite the funds being poured into the project.

Since I have read about the variety of tasks an Arduino can perform, I was just a bit pissed off at them having come up with nothing in a year and so much money. So I thought: why not give them a run for their money, and come up with something myself.

What I thought about was something like the following.
The system needs at least one Arduino with at least two shields plugged into it. As far as I know, there are 'shield splitters', which can be used to achieve this. One of the shields would be an RFID shield, to read a serial number off the RFID passes (very simple cards, with only a serial number as their payload).
These would be transmitted along a network connection, either via a CAT5 or WLAN shield, to a server at each subway station. These forward the serials to a central server, storing all the serial numbers, and a record of the balances associated, in a database. The server then looks up the sent serial, and charges the card by deducting the appropriate amount from the balance. If the remainder is positive, it sends back a TRUE response, if not, a FALSE.
The computer at each station parses these responses, and send, say, a 1 if the response was TRUE, a 0 if the response was FALSE. If the Arduinos can handle THREE shields, the thrid would be a servo, which, upon the chip receiving a 1, would turn the turnstiles, letting the passanger through. On receiving a 0, the chip would sound some sort of alarm (possibly a klaxon via a different motor on the shield), alerting the conductors. If not, the motors could probably be controlled by a second Arduino, on the same principle.

Without knowing the probable extra costs, I would say a system like this could be implemented with a far smaller cost, then whatever convoluted (and essentially flawed) system our developers come up with, as their objective seems to be driving up costs and prolonging development time, rather than delivering a functional system. At least experience shows that... :frowning:

Now, this is just my novice idea, and my question would be whether this can be made to work, or if you have any thoughts/suggestions on this matter, I would be glad to hear them. :slight_smile:

Thank you in advance!

recently, there has been a scandal in the media about how the government public transport company spent tens of millions of forints to research the feasibility of an RFID pass system, as well as developing the systemwith no results after a year, despite the funds being poured into the project.

OH MY GOD!

This does not sound like a problem that is too difficult to solve.

I would solve this using a client/server system design.

All Arduino RFID readers can be thought of as clients, and the mainframe computer as a server.

You need a few components: (all of which should be relatively easy to create)

  • Client

  • Read RFID

  • Send RFID on a network (Ethernet shield and library comes to mind)

  • Recieve messages on a network (see links above)

  • Server

  • Recieve RFID data

  • Validate Data

  • Calculate balance

  • You may want a frontend for customers and/or employees? A way to add to the balance (user pay for tickets), and maybe a way for employees to modify this as well (fees, tickets, somethingelse?)?

  • Properly respond to the clients

I would implement the clients as a finite state machine. Maybe with these states:

  • Connect

  • Wait for a connection to a server

  • Standby

  • Wait for a customer

  • Reading

  • Reading the RFID

  • Validating

  • Wait for the server to respond, is this a valid customer?

  • Alarm

  • An error has ocurred [User error or System error]?

The server could/should be implemented as a multithreaded event based system.
It should try to serve the client request immediately.

You will also need a robust protocol.
It should accept variable data packet lengths (efficiency)
It should have some kind of CRC (security)
It should support both node to node and broadcast transmissions. (versatility)


By the way:
This sounds like a very cool project!
Good luck :slight_smile:

Is there any automation in the system to start with, or is ticketing all done manually?

Washington, DC has had a RFID pass system for a few years now, which works exactly as you described--the pass is scanned on entry into a station, and when you exit your fare is calculated based on origin and destination and deducted from your balance. There are machines in each station that can read and add to that balance with cash or credit cards.

Of course, there was already an electronic farecard system in place using paper magstrip cards with electronically controlled gates, so the infrastructure for it didn't have to be built up from nothing.

Google tells me that 10,000,000 forints is equivalent to about US$52,000 which doesn't sound too unreasonable at all if it means a lot of new infrastructure. Remember that it's not just developing the technology (like you said, that part is easy), but also taking a thorough look at staffing costs, customer impact, transaction timing, etc. Those need to be evaluated LONG before you start rolling out something like this.

What happens if you roll out a shiny new RFID pass system only to discover that station uplinks are too slow, or your central server can't handle the peak load, and your customers are standing there waiting three seconds for their cards to be validated before the gate opens at rush hour? I don't know about the transit system in question, but I can tell you with full certainty that that kind of delay on every transaction would be disastrous at rush hour in DC.

@ajb: No automation as far as I know, the tickets have a set price, and are valid for a given time period. Theoretically, there's also a travel length limitation, but this doesn't seem to be enforced.
As for the costs and time, I was writing from memory, but it didin't seem right, so I checked the figures on the net. The project was started in 2004, with a budget of 20 BILLION HUF, and so far, five years later, no results. That's what pisses me off, as it should have showed SOME things, but so far, nothing. That's why I thought I'd give this a try, to see how much it would cost with a bit of creativity, and off-the-shelf components. Probably less than 10 million :wink:
Overloading, yes, we know that: our university education is controlled by a software codenamed NEPTUN, which is poorly written, and can't handle load during exam and course registration times. The two most important days :smiley: But yes, here in Budapest, such a bottleneck could prove disasterous. We're nowhere near as big as DC, but big enough to have serious issues with mass transit.

@AlphaBeta: Thanks for the extensive breakdown, so my idea is basically workable, now to fill in the details...
I am going to ask for help now and again (probably quite often :D) regarding the coding, as I usually learn these things on the fly, and I know next to nothing yet :slight_smile:
I have just downloaded the developers package, and I'm reading up on the languages used. Is your FSM lib stable and ready to be used? If it is, I'll probably try to use it to create the Finite State Machine solution you recommended.
However, I think the greater challenge will be the server side, to get the database to evaluate the requests properly, and the intermediaries to parse the responses and send the proper triggers to the Arduino...

I am going to ask for help now and again (probably quite often :D) regarding the coding, as I usually learn these things on the fly, and I know next to nothing yet :slight_smile:

Asking questions, and maybe answer some. That is what this forum is all about :slight_smile:

I have just downloaded the developers package, and I'm reading up on the languages used.

Arduino language is C/C++, but it has some abstractions.

The Arduino API is also modeled a bit after JAVA,(which is good) in my opinion.

Is your FSM lib stable and ready to be used? If it is, I'll probably try to use it to create the Finite State Machine solution you recommended.

It is stable. I use it as a backend for a lot of my projects.

If you have questions, do not hesitate to contact me by PM or mail. :slight_smile:

However, I think the greater challenge will be the server side, to get the database to evaluate the requests properly, and the intermediaries to parse the responses and send the proper triggers to the Arduino...

This will probably be the hard part.

For your 'Proof of concept' I think a java/proceccing application will suffice.


Are you an employee in this research team, or an outsider with a curios mind? [not to say that the researchers are not curious as well]

[edit]I regret saying it was relativeley easy, without indicating I though it relative to the budget. Not relative to you. I'm sure you'll find lot's of fun challenges (I know I would) :)[/edit]

The project was started in 2004, with a budget of 20 BILLION HUF, and so far, five years later, no results.

Ahh, that's quite a bit different then. :o

I'm just an outsider. I mainly got into this to see if I can do something the dev-teams seemed unable to. On the other hand, they were probably thinking in custom microcontrollers and new hardware and stuff. What I love about this little board is that you can pretty much replace an expensive custom microcontroller with a bit of creativity and a good idea.

Regarding the FSM: I need to declare custom funtions at the beginning of the sketch, then enter the funtions' handles when declaring the states, right? The reference isn't really clear on that, at least not for me... :-[

What I love about this little board is that you can pretty much replace an expensive custom microcontroller with a bit of creativity and a good idea.

Arduino is brilliant! :smiley:

Regarding the FSM: I need to declare custom funtions at the beginning of the sketch, then enter the funtions' handles when declaring the states, right? The reference isn't really clear on that, at least not for me... :-[

The States can be created with a single callback function. Such as the states I use in the example below.
Or, you can assign a ON_ENTER and a ON_EXIT function.
These functions are called only once (as opposed to the ON_UPDATE function that will be called every time the FSM is updated in that current state).

Silly LED Example:

The sketch below uses external transitions, caused by a user and their button presses.
Each button press will cause the FSM to advance to the next State in the diagram above.

//http://www.arduino.cc/playground/uploads/Code/FSM.zip
#include <FiniteStateMachine.h>
//http://www.arduino.cc/playground/uploads/Code/Button.zip
#include <Button.h>
//http://www.arduino.cc/playground/uploads/Code/LED.zip
#include <LED.h>

const byte NUMBER_OF_STATES = 4; //how many states are we cycling through?

//initialize states
State On = State(ledOn);
State Off = State(ledOff);
State FadeIn = State(ledFadeIn);
State FadeOut = State(ledFadeOut);

FSM ledStateMachine = FSM(On); //initialize state machine, start in state: On

Button button = Button(12,PULLUP); //initialize the button (wire between pin 12 and ground)
LED led = LED(11); //initialize the LED
byte buttonPresses = 0; //counter variable, hols number of button presses

void setup(){ /nothing to setup/ }

//poor example, but then again; it's just an example
void loop(){
if (button.uniquePress()){
//increment buttonPresses and constrain it to [ 0, 1, 2, 3 ]
buttonPresses = ++buttonPresses % NUMBER_OF_STATES;
switch (buttonPresses){
case 0: ledStateMachine.transitionTo(On); break;
case 1: ledStateMachine.transitionTo(Off); break;
case 2: ledStateMachine.transitionTo(FadeIn); break;
case 3: ledStateMachine.transitionTo(FadeOut); break;
}
}
ledStateMachine.update();
}

//utility functions
void ledOn(){ led.on(); }
void ledOff(){ led.off(); }
void ledFadeIn(){ led.fadeIn(500); }
void ledFadeOut(){ led.fadeOut(500); }
//end utility functions

This is a 'safe' network debug state:
State ethernetDebugState = State( connectToHost , debug , closeConnectionToHost );
It assures you that by the time debug() gets called a connection is provided. It also sees to it that when changing state, the connection to the host is closed.
If you want to keep a connection simply rewrite it to this:
State ethernetDebugState = State( connectToHost , debug , NO_EXIT );

NB: These states relies on connectToHost, debug and closeConnectionToHost to be implemented.

Okay, I've hit a bit of a design speedbump: how do I get the processor to listen for a specific char on the ethernet port? I know I could use the serial monitor if I were using the USB, but here I'm using a PC to mediate between the DBserver and the Arduinos.

The main problem is that if I use the write function of the Server object, it broadcasts, but this would result in a single swipe triggering all gates/alarms simultaneously. Can I use something in the Ethernet library to listen for a specific char being sent in on the interface?

The closest I can come right now is to have all clients listen for a specific pair(one for approved, one for denied), so that even though the server broadcasts them, they will only trigger the reaction in the one client listening for them.

The problem here lies in getting the server to choose the proper pair to send. I thought of giving each reader a locally unique ID to send to the server, where it is stored in a separate variable, from which a four-path if-then-else statement chooses the correct pair to send, but this raises collision issues: if two readers send at the same time, only one will get a response, as one will overwrite the ID in the variable.

@AlphaBeta: Thanks for the revised library, I'll be sure to replace the beta :slight_smile:

I do not know how you've implemented this.

But this: Ethernet - Arduino Reference

Uses:

if (client.available()) {
  char c = client.read();
}

Nothing stops you from:

const char TARGET = 't';
if (client.available()) {
  char c = client.read();
  if (c==TARGET){
    //a specific char was found
  }
}

Sorry if I overlooked something.

This is the easier part, I got this far. My problem is how to make the server send out the correct character.

You see, the gates should be independently triggered. That means all readers need to react to different trigger chars from the servers, otherwise they would all trigger every time any one did. So the server has to choose the correct pair, and send the appropirate char. This choice is the problem.

I thought of having each client send an ID before it sends the data, which would be stored at the server. Then the server goes through a four-path if-then to determine which client just sent, and which char pair to use. The problem with this one seems to be a potential (and probable) collision: if another client sends before the first one is processed fully, the variable will be overwritten, and the wrong character gets sent as a result.

Shall I write out the appropirate bits of code, so it will be easier to see? :slight_smile:

I'd love to see some code.

When you speak of the server, is this also an arduino? Or is this a computer?

For now, I was thinking of another Arduino that acts as a mediator to translate the network into USB-serial. I'm not at the PC-side yet...

Reader-side

      if(bytesread == 16) {              // if 16 digit read is complete(tag serial) 
passcheck_1.write(ID); // A preset string, locally unique ID        
passcheck_1.write(code); // the read serial
      }

Mediator-side:
That is still theoretical, but the server would first check if the incoming data is equal to one of the n IDs, and if yes, it would store it in, say, clientID.

Then:

if clientID = ID1{
   reader_select_machine.transitionTo(reader1)
{
   if clientID = ID2{
reader_select_machine.transitionTo(reader2)
}
}

And so on for all required readers

This would select one reader, and the appropriate state would specifiy which chars to use.

Won't the IP be sufficient for identifying a client?

[ I have no experience with the ethernet shield and library, unfortunantly ]

That was my first thought too, but I don't know how to get that. I mean it's obviously there, in device memory somewhere, but I don't know how to get it out into a variable...

And I have no experience with anything, I'm learning on the fly... :slight_smile:

Well, I hopefully got it to work now, sorta. My idea was to first read nine bytes on the eth port, the length of the id string each reader sends out. then the first nine bytes are passed into the idstring variable, after which next 16 bytes are read, which are passed to the serial port, as they are the payload code. This should ensure that the two strings are properly separated.
The compiler gives me an error, as the eth port reads into a separate variable to buffer it, which is initialised without a size, but is increased as the port reads data (the code contains an incrementing counter, which at one point is used as the size of the buffer string).

int bytesread;
char bufferstring[] = {}
later:
bufferstring[bytesread]

This means the program compiles with an error that conversion from char[0] to char[9] is invalid, but I think this is actually just a result of the compiler being unable to follow the program as it actually executes, so it should not be a problem when actually deployed, no?

I know it will all be easier to imainge and understand once I get some code up, but that will only happen tomorrow, as I'm working without a net access on my own computer this weekend.

int bytesread;
char bufferstring[] = {}
later:
bufferstring[bytesread]

Need to be more like:

const byte bytesread = 9;
char bufferstring[bytesread] = {0};

This way the compiler knows the size of bufferstring when creating space (allocating) for it.
:slight_smile:

Yes, I thought of that too, but all input from the eth port is buffered in that string, both the 9-byte ID, and the 16-byte payload. That's why I had to work around like this, as it has to deal with both a 9 and a 16-byte string.

  char idstring [9] = {};
char bufferstring[] = {};
  char payloadstring[16] ={};
  int temp = 0;
  int bytesread = 0;
  if (client.available() > 0)
  {
    if ((temp = client.read()) == 27)
    {
      bytesread = 0;
      while (bytesread<9)
      {
        if (client.available() > 0)
        {
          temp = client.read();
          if (temp == 9)
          {
            break;
          }
          bufferstring[bytesread] = temp;
          bytesread++;
          if (bytesread == 9)
          {
            idstring = bufferstring;
          }
        }
      }
      bytesread = 0
        while (bytesread<16)
      {
        if (client.available() > 0)
        {
          temp = client.read();
          if (temp == 16)
          {
            break;
          }
          bufferstring[bytesread] = temp;
          bytesread++;
          if (bytesread == 9)
          {
            payloadstring = bufferstring;
          }
        }
      }
    }
  }


  lcd.print(payloadstring);
  Serial.print(payloadstring);
  bufferstring = 0;
}

Here's the whole separating code part. Kinda convoluted and messy, but I've just started programming in C :smiley:

You still need to define the bufferstring with a size.

char bufferstring[16] = {'\0'}; //replace 16 with the maximum length of bufferstring

Well, it's been a while since I last visited this forum, or at least it feels like a lot of time. Since then, this project went from speculation into an actual, implementable coding project, being done on both the Arduino platform, and on PC in C/C++/mySQL. So yeah, it developed a bit...:smiley:

Still, since this would be my very first time programming something of this kind, I would like a bit more help: the codes seem to compile fine, but I would like to see if human eyes can spot any irregularities/improvements in my code.

Reader code: http://pastebin.com/m19ee2851
Mediator code: http://pastebin.com/m5c2f236f

Thank you very much for your time, and your names will be included in the source. :slight_smile: