It is a serial bus that has TX and RX, it works best to connect only two devices, is a common protocol because is included on the Arduino Boards and also can be used to debug usign a FTDI adapter to USB and read the values from any computer.
We will connect two projects with serial communication to send data collected by my Light Sensor and see how Daniela's board responds based on the data sended.
See more details on our group pageFor this I only modify the existing code that was measuring the raw value from the LDR and approximating the lumens it represents, and compare it with some threshold values, to also send this data over serial port with a predefined 'character code' from which you can see more here
Serial bus snippets used on the group assignment
CustomSerial.begin(9600); //Initialize serial communication
CustomSerial.println('a'); //Send the code for light needed
CustomSerial.println('d'); //Send the code for light not needed
On the code snipped above you can see the key parts of the serial communication extracted from the code. Is important that the sender/receiver baud rate matches.
See the Group Assignment codeIs an addressable bus that uses two wires, SCL (Serial Clock Line) and SDA (Serial Data). It uses a master/slave denomination, where the master initiate the transmission and clock signal, the slave listen to the addresses, and when it matches it can receive or send data from and to the master device.
The idea was to make the previously made boards as peripheral sensors, and use my main board to read the values. This is the way I intended to connect peripheral sensors and my main board on my final project.
I intended to use I2C, to program the peripheral I follow this tutorial, as the original program to measure light (you can see how it was coded here) use on that board was write using arduino. Following this tutorial wasn't that easy, because on the git repo the master branch isn't working, you have to download the rollback branch.
To troubleshoot I use an Arduino Uno as master to communicate with my peripheral board, test the addresses and the value sended using the serial port.
The TinyWireS library has a begin() function were you define the peripheral address, and then you can hook custom functions too manage the onReceive and onRequest from the controller. I only use the onRequest function to send 1 byte back.
void requestEvent(){
int test = 26;
TinyWireS.send(test);
}
When that was working I split the 16bit value from the measurement on to lowByte and highByte and sent those via I2C bus. On the master I request two bytes and reassemble the 16bit number.
//Peripheral
void requestEvent(){
TinyWireS.send(lowByte(ilum));
TinyWireS.send(highByte(ilum));
}
//controller (test code for Arduino UNO)
void loop() {
int bytesRecived = Wire.requestFrom(4,2); // 4 is the hard coded address
Serial.print(bytesRecived); // used to debug
Serial.print(" ");
while(Wire.available()){
byte low = Wire.read();
byte high = Wire.read();
int lightValue = low | (high<<8);
Serial.println(lightValue); // used to debug
}
delay(500);
}
On the Output devices week I program the board to multiplex and sense the touch input, all of this was written in C/C++ using direct port manipulation that allow me to have more speed to multiplex.
The I read the ATmega328p datasheet and I found that make the protocol via direct port manipulation will require a lot of work. I decided to browse for a library that may reduce the work needed. I couldn't find any that I manage to compile my code with. So I decided to use the Arduino core and use the Wire.h library. I use PlatformIO and place my C code there to use the multiplexed display.
Both boards were programmed using the FabTinyISP and ths SPI protocol.
I the use almost the same code used on the Arduino Uno, and display the 16 bit value on the 4 digit display.
void DisplayInt(int value){
if(value>9999) return;
uint8_t buffer[4] = {10,10,10,10};
for (uint8_t i = 0; i < 4; i++)
{
buffer[i] = value%10;
value = value /10;
}
//Set the display digits
displayDigits[1] = buffer[3];
displayDigits[2] = buffer[2];
displayDigits[3] = buffer[1];
displayDigits[4] = buffer[0];
}
I was only getting 255 or -1 value from the peripheral board. That is an error message, the solution was to use the rollback branch that can be found here. Is the older version that works as intended, this is noted on the Github issues of the repository.
The I2C protocol is based on a open drain bus, that allow the communication between IC's with different voltages. But that means that each line needs a pull-up resistor, it can be calculated for specific needs using This considerations but the standard value is of 4.99KΩ.
The I2C protocol was very attractive to me because I feel that it could be the perfect way to communicate different boards on my final project.
After this week I was a bit overwhelmed by the code but using the arduino core and libraries it become much easier, even though I like the idea of this been used on my final project.