The goal of this firmware is to manipulate the information inputted by the user via GUI so it can be properly transmitted. In this project we chose to implement the concept which is behind a common numerical modulation: Frequency Shift Keying (FSK). The data is transferred from the PC to the Arduino board via serial communication. Each datum is encoded as a string, so we need to convert it into a numeric type variable, which can be easily done with Arduino's library functions. Once the datum is a numeric variable, ie BYTE (8 bits) or FLOAT (32 bits). It is possible to access every single bit of the BYTE variable again by using a library function. Instead for a FLOAT variable it is a bit more difficult since we had to declare a STRUCT in order to extract the single bits of the digital number.
Once the extraction of bits is done, the focus shifts on how to transmit the values. We based our transmission method on the FSK concepts: in the modulation, the '0' value is assigned to a specific frequency while the '1' value is assigned on a different frequency. So in our project we decided to assign a frequency of 250 Hz (4 ms) to '0' value and 500 Hz (2 ms) to '1' value while our carrier has a frequency of 125 Hz (8ms). The signal on the output pin is a square wave and these frequency ensure that there's no flicker on the emitted light. In order to properly synchronize the receving and transmitting devices we employed a header consisting in a sequence of 56 fixed bits which are '0' and '1' alternating. This way it is possible to know how many signal edges have to be read by the receiver to know that there's a transmission of data incoming and the edges are not due to noise or interference.
The version of the firmware used in the transmitting Arduino can be found here
This part is a bit trickier because we have to rely on Arduino built-in circuitry for the reading of the signal which will be then properly demodulated to reconstruct the original data. Knowing how the transmission works, we implemented an interrupt routine to count the rising edge of the signal on the input pin. The interrupt signal is set on the rising edge so everytime the voltage surpasses a threshold specified in the Arduino datasheet, a counter is increased and then used to know how many edges we received. This is why the signal integrity is crucial: if a noise is applied to it there's the possibility that the reading will be corrupted if the circuitry inside Arduino misinterprets the transition from low to high (ie the signal isn't monotonic in a neighbourhood of the threshold). And that is also reason why we used the hex inverters in the 74HC04 chip: the inverters provide a shaper shape of the signal granting a faster and more defined transition removing the influence of the noise.
Once the signal is properly conditioned to be read, the firmware is in charge of counting how many edges are received in a fixed amount of time so that it is possible to discern wheter a '0' or a '1' was sent. More specifically, given our carrier is at 125 Hz we know that in a period we receive 4 rising edge if a '1' was transmitted (500/125 = 4) while on the other hand if we receive 2 edges we know that a '0' was transmitted.
Thanks to the header sent by the transmitter it is possible to properly synchronize the receiver to the data and so we manage to reconstruct what was sent, specifically the ID of the tag and the price.
We developed a basic graphic user interface with the help of Microsoft Visual Studio in order to handle the communication between the user PC and the Arduino chip using the serial port communication. In this interface it's possible to specify the device ID we want to update and also the price we want to set. Since the program relies on the microsoft framework for the serial communication we use a USB port that acts like a serial port and from a selection bar it is necessary to specify to which port the device is connected. It's important to mention that if you connect to the device via this interface there's no possibility to employ the serial monitor built in the Arduino IDE, which we use to verify if the receiver interpreted correctly the received signal.
The source code for the GUI app can be found here