i am using 2 UART lora one transmit and the other receive using arduino for both data sent for LDR was around 350 and accelerometer was 605 i have 2 variable to send the transmitting:
#include <SoftwareSerial.h>
SoftwareSerial mySerial(6, 7); // RX, TX
int LDR_Pin = A0; //analog pin 0
int y=A1; //y axis variable
int pirPin = 5; //the digital pin connected to the PIR sensor's output
void setup(){
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}
mySerial.begin(9600);
}
void loop(){
int vert = analogRead(y);
int LDRReading = analogRead(LDR_Pin);
int result = LDRReading/4;
mySerial.write(result);
Serial.print("LDR : ");
Serial.print(LDRReading);
delay(1000);
mySerial.flush();
int acc = vert/4;
mySerial.write(acc);
Serial.print(" acc: ");
Serial.println(vert);
mySerial.flush();
delay(1000);
}
to receive
#include <SPI.h>
#include <Client.h>
#include <Ethernet.h>
#include <Server.h>
#include <Udp.h>
#include <SoftwareSerial.h>
SoftwareSerial mySerial(6, 7); // RX, TX
int LDR_Pin = A0; //analog pin 0
int y=A1; //y axis variable
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; //physical mac address
byte ip[] = {}; // ip in lan
byte gateway[] = {}; // internet access via router
byte subnet[] = {}; //subnet mask
EthernetServer server(80); //server port
void setup() {
// initialize serial communication:
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}
mySerial.begin(9600);
Ethernet.begin(mac, ip, gateway, subnet);
}
void loop(){
int vert = mySerial.read();
int acc =vert*4;
Serial.println(acc);
mySerial.flush();
delay(1000);
mySerial.flush();
int LDRReading = mySerial.read();
int result = LDRReading*4;
Serial.println(result);
mySerial.flush();
delay(1000);
EthernetClient client = server.available();
if (client) {
Serial.println("Connected");
client.println("<!DOCYTYPE html>");
client.println("<html>");
client.println("<title>Sensor Hub</title>");
client.println("<head> <meta http-equiv='refresh' content='1;http://' /> </head>");
client.println("<body bgcolor='#FFFFFF'>");
client.println("<center><h1>this is sensor webpage indicator.</h1></center>");
client.println("<script src='https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js'></script>");
client.println("<script type='text/javascript'>");
client.println("$.ajax({");
client.println("type: 'POST',");
client.println("url: 'http:// /fyp/write.php',");
client.print("data: { LDRReading: '");
client.print(result);
client.print("', acc:'");
client.print(acc);
client.print("'}");
client.println("");
client.println("});");
client.println("</script>");
client.println("</body></html>");
client.stop();
}
}
but when i am checking my database i find my accelerometer data in my LDR database column and vice versa sometimes
i am unsure on how to fix the problem and is it possible to give an ID to the variable data to prevent data switching?
Apart from what gre_gor said in a comment (so for reading and writing an integer you need to send and receive two bytes) you need a stronger way to send and receive the bytes (simply waiting and praying for them to be synchronized is not an option).
There are tons of way to make a suitable protocol. In your ideal protocol you need a way to determine the start and/or end of the data, and a way to determine WHAT data is being transmitted.
If you use ascii representation (i.e. with print
and println
s) you can use a non-printable character or a space or a new line to set this. Since you are using the write
, however, I'm going towards a more "byte saver" technique.
In a byte oriented transmission I usually found two ways of dealing with this.
The first one is to use a set of reserved bytes and an "escape" one. Whenever you get one reserved byte you put an escape and then modify the byte in order to set it non-reserved. For instance, if you define 7D and 7E as reserved, and define 7E as escape byte (and for instance 7D is the end of transmission, and you make a reserved into a non-reserved by changing the 7 in a 8) if your byte array is 01 34 7D 66 7E then you transform the 7D in 7E 8D (escape + non reserved=, the 7E in 7E 8E, and append a 7D. This way you send 01 34 7E 8D 66 7E 8E 7D. The parser waits for the 7D, and knows that whenever it receives the 7E it discards that byte and changes the following 8x into 7x.
This is an easy way to make a more robust protocol, but has a drawback that the output has a variable length. The alternative I often use when I need to send data which is shorter that 8 bits (or a multiple) is to reserve a bit for indicating if the byte is a data or a command, then use the other 7 bits to store the actual data. I'm using this approach in your case, assuming that the two variables you are sending are signed and with a range 16383 - -16384.
So, the protocol is simple. if the first bit of the received byte is a 1, then this is a command. Valid commands are:
0x80 Accelerometer data
0x81 LDR data
(you can add your own ones, but all of them should start with a 1 bit)
All the commands should be followed by two data bytes, and each data byte starts with a 0 bit. The composition is
bit position 7 6 5 4 3 2 1 0
1st byte '0' b13 b12 b11 b10 b09 b08 b07
2nd byte '0' b06 b05 b04 b03 b02 b01 b00
Where '0' is a 0 bit, and bxx is the xx-th bit of the data being transmitted.
Now, sending the data is simple. This simple code can do it:
#define SEND_ACCEL_DATA 0x80
#define SEND_LDR_DATA 0x81
void sendData(uint8_t type, int value)
{
mySerial.write(type);
mySerial.write((value >> 7) & 0x7F); // Upper 7 bytes
mySerial.write(value & 0x7F); // Lower 7 bytes
// Never needed to call flush, but if you need it put it here
}
usage:
sendData(SEND_LDR_DATA, ldr_value);
sendData(SEND_ACCEL_DATA, accelerom_value);
As you can see you are just sending the type followed by the values.
The receive code is simple too:
#define SEND_ACCEL_DATA 0x80
#define SEND_LDR_DATA 0x81
if (mySerial.available() >= 3)
{
switch (mySerial.read())
{
case SEND_ACCEL_DATA:
{
int acceleration = mySerial.read() & 0x7F;
acceleration = (acceleration << 7) | (mySerial.read() & 0x7F);
if (acceleration & 0x2000) acceleration |= 0xC000; // This is the sign extension
// now you can use acceleration (and store it in the database)
}
break;
case SEND_LDR_DATA:
{
int ldr = mySerial.read() & 0x7F;
ldr = (ldr << 7) | (mySerial.read() & 0x7F);
if (ldr & 0x2000) ldr |= 0xC000; // This is the sign extension
// now you can use ldr (and store it in the database)
}
break;
}
}
If you want, you can embed this in a function too:
#define SEND_NONE 0x00
#define SEND_ACCEL_DATA 0x80
#define SEND_LDR_DATA 0x81
int getDataFromSerial(uint8_t *p_type)
{
int result = 0;
*p_type = SEND_NONE;
if (mySerial.available() >= 3)
{
switch (*p_type = mySerial.read())
{
case SEND_ACCEL_DATA:
case SEND_LDR_DATA:
int result = mySerial.read() & 0x7F;
result = (result << 7) | (mySerial.read() & 0x7F);
if (result & 0x2000) result |= 0xC000; // This is the sign extension
break;
default:
*p_type = SEND_NONE;
break;
}
}
return result;
}
// Usage
uint8_t type;
int result = getDataFromSerial(&type);
switch (type)
{
case SEND_ACCEL_DATA:
// result is the acceleration
break;
case SEND_LDR_DATA:
// result is the ldr
break;
}
Just beware that you WON'T receive both data at the same time, but one after the other. If you need the data to arrive at the same time, ask and I'll upload a modified version to send and receive both data at the same time.
EDIT: as asked, here is the version with the data travelling together.
Now, if you group the two data together the type of packet is just one. So there is no need for a byte stating what type of byte it is. So you can modify the protocol to just report if the byte is the starting one or not. The protocol now just has one type of packet, which is 4 bytes long:
bit position 7 6 5 4 3 2 1 0
1st byte '1' l13 l12 l11 l10 l09 l08 l07
2nd byte '0' l06 l05 l04 l03 l02 l01 l00
3rd byte '0' a13 a12 a11 a10 a09 a08 a07
4th byte '0' a06 a05 a04 a03 a02 a01 a00
where l13-l00 are the fourteen bits of the LDR value, and a13-a00 are the ones for the acceleration.
The sending is modified, but is simple once you know what to send:
void sendData(int ldr, int accel)
{
mySerial.write(((ldr >> 7) & 0x7F) | 0x80); // Upper 7 bytes and first bit
mySerial.write(ldr & 0x7F); // Lower 7 bytes
mySerial.write((accel >> 7) & 0x7F); // Upper 7 bytes
mySerial.write(accel & 0x7F); // Lower 7 bytes
}
usage:
sendData(ldr_value, accel_value);
The only thing worth noting is that the first byte has the highest bit set, while the other bytes haven't.
The receiving code simply has to wait for all the four bytes to arrive, checking that the first one actually starts with a 1, and then recover the two values exactly like the previous way:
while (mySerial.available() >= 4)
{
if (!(mySerial.peek() & 0x80))
{ // If the first byte in the buffer is not a valid start, discard it
mySerial.read();
continue;
}
int ldr = mySerial.read() & 0x7F;
ldr = (ldr << 7) | (mySerial.read() & 0x7F);
if (ldr & 0x2000) ldr |= 0xC000; // This is the sign extension
int acceleration = mySerial.read() & 0x7F;
acceleration = (acceleration << 7) | (mySerial.read() & 0x7F);
if (acceleration & 0x2000) acceleration |= 0xC000; // This is the sign extension
// now you can use acceleration and ldr (and store them in the database)
}
}
If you prefer a function, you can implement it this way:
boolean getDataFromSerial(int *p_ldr, int *p_accel)
{
boolean foundData = false;
while ((!foundData) && (mySerial.available() >= 4))
{
if (!(mySerial.peek() & 0x80))
{ // If the first byte in the buffer is not a valid start, discard it
mySerial.read();
continue;
}
*p_ldr = mySerial.read() & 0x7F;
*p_ldr = ((*p_ldr) << 7) | (mySerial.read() & 0x7F);
if ((*p_ldr) & 0x2000) (*p_ldr) |= 0xC000; // This is the sign extension
*p_accel = mySerial.read() & 0x7F;
*p_accel = ((*p_accel) << 7) | (mySerial.read() & 0x7F);
if ((*p_accel) & 0x2000) (*p_accel) |= 0xC000; // This is the sign extension
foundData = true;
}
}
return foundData;
}
usage:
int accel, ldr;
if (getDataFromSerial(&ldr, &accel))
{
// use accel and ldr
}
In this case the two variables always go together, while in the other you can send them separately. Which is better? It depends on what you need. This is easier and more effective, the other is more flexible.
EDIT 2: Complete example:
I designed a complete example of two arduinos communicating with the latest protocol (2 data together). The one on the left generates the two values starting from two potentiometers, the other prints them.
Here you can find it: https://circuits.io/circuits/3690285-software-serial-binary-transmission
Connections:
Sender code:
#include <SoftwareSerial.h>
SoftwareSerial mySerial(10, 11);
void sendData(int ldr, int accel)
{
mySerial.write(((ldr >> 7) & 0x7F) | 0x80); // Upper 7 bytes and first bit
mySerial.write(ldr & 0x7F); // Lower 7 bytes
mySerial.write((accel >> 7) & 0x7F); // Upper 7 bytes
mySerial.write(accel & 0x7F); // Lower 7 bytes
}
// the setup routine runs once when you press reset:
void setup() {
Serial.begin(9600);
mySerial.begin(2400);
}
// the loop routine runs over and over again forever:
void loop() {
int ldr_value = analogRead(A0);
int accel_value = analogRead(A1);
sendData(ldr_value, accel_value);
// Print it on the serial interface for debug
Serial.print("TX LDR: ");
Serial.print(ldr_value);
Serial.print(" - ACC: ");
Serial.println(accel_value);
delay(1000);
}
Receiver code:
#include <SoftwareSerial.h>
SoftwareSerial mySerial(10, 11);
boolean getDataFromSerial(int *p_ldr, int *p_accel)
{
boolean foundData = false;
while ((!foundData) && (mySerial.available() >= 4))
{
if (!(mySerial.peek() & 0x80))
{ // If the first byte in the buffer is not a valid start, discard it
mySerial.read();
continue;
}
*p_ldr = mySerial.read() & 0x7F;
*p_ldr = ((*p_ldr) << 7) | (mySerial.read() & 0x7F);
if ((*p_ldr) & 0x2000) (*p_ldr) |= 0xC000; // This is the sign extension
*p_accel = mySerial.read() & 0x7F;
*p_accel = ((*p_accel) << 7) | (mySerial.read() & 0x7F);
if ((*p_accel) & 0x2000) (*p_accel) |= 0xC000; // This is the sign extension
foundData = true;
}
return foundData;
}
// the setup routine runs once when you press reset:
void setup() {
Serial.begin(9600);
mySerial.begin(2400);
}
// the loop routine runs over and over again forever:
void loop() {
int accel, ldr;
if (getDataFromSerial(&ldr, &accel))
{
// Print it on the serial interface for debug
Serial.print("RX LDR: ");
Serial.print(ldr);
Serial.print(" - ACC: ");
Serial.println(accel);
}
}