Maker Pro
Maker Pro

Serial communications protocol

Anon_LG

Jun 24, 2014
453
Joined
Jun 24, 2014
Messages
453
This program is the first serial communications protocol I have wrote, attached are 2 separate programs, the 2 are corresponding send and receive programs. I have no experience in serial communications, I just thought it might be fun, I may have copied a previous method I may have come up with something new. They are written using the Arduino IDE. The programs are designed to send a byte of data (transmitted as an array) with a starting "measuring" bit before each transmission. I have used what I know about logic, and try to see the program from the reciever's and transmitters point of view. the acronym title "LaC" stands for length and change, the key elements on this protocol, effectively the change is used as a clock pulse and the length represents a 1 or 0 in the array, the measuring bit is always a long bit, this gives the reciever something to work with. The program has no check sum, no security and no collision avoidance, these will be added at a later date, I designed the protocol to be small in memory size, taking up less than a half of an Attiny85's memory and I aim to keep it under half with a checksum and collision avoidance, this will still allow usable space on the microcontroller. If this protocol is completed successfully I hope to make it into a project showcase.

The only thing you may not notice is that the send and recieve functions do eventually align due to the "givelength()" and "Recievelength()" have multiple pulses in the functions, the recieve script will not change the variable "firsttime" until the conditions are met defining a starting position and the length of the long HIGH/LOW. The variables are a little messy, I intend to clear those up once I know whether this protocol is expected to ever work.

I would be appreciative if members pointed out any problems or improvements to the protocol,

transmit:

Code:
int Recievepin = 0;
int Sendpin = 1;
int Longcount = 0;
int firsttime = 1;
int sfirsttime = 1;
int bytepos = 0;
int bytelengths[8] = {
  0, 0, 0, 0, 0, 0, 0, 0};
int bytebinvalue[8] = {
  0, 0, 0, 0, 0, 0, 0, 0};
int bytecount = 0;
byte change0 = 0;
byte change1 = 0;
byte calcdat = 0;

int datar = 0; /////////This is the variable that can be transmitted using a copy of the code on a corresponding microcontroller asign actions to values for transmission
int datas = 0; /////////This is the variable that can be sent to a corresponding microcontroller with a copy of the code asign values to actions for reception

/////////////////////////////////////////////////

void setup(){
  pinMode(Recievepin, INPUT);
  pinMode(Sendpin, OUTPUT);
}

void loop(){
  delay(1);
  //commands to recieve data
  asignsendvalue();
  sendlengthofvaluebuffer();
  sendbyteloop();
}

//////////////////////////////////////////////////

//functions for recieving data (removed in this version)

// above are the functions for recieving data (removed in this version)

// below are the functions for sending data

void givelength(){
 
 
    for(int i = 0; i > 16; i++){
      digitalWrite(Sendpin, HIGH);
      delay(1);
    }
 
  digitalWrite(Sendpin, LOW);
 
  delay(30);
 
     for(int i = 0; i > 16; i++){
      digitalWrite(Sendpin, HIGH);
      delay(1);
    }
   
  digitalWrite(Sendpin, LOW);
  delay(5);
  sfirsttime = 0;
}

void asignsendvalue(){
  calcdat = datas;
  for(int i = 7; i<=0; i = i - 1)
  {
    if(calcdat >= 2^i){
      bytebinvalue[i] = 1;
  }
    else{
      bytebinvalue[i] = 0;
  }
    calcdat = calcdat/2;
  }
}

void sendlengthofvaluebuffer(){
  bytecount = 0;
  while(bytecount < 8){
    if(bytebinvalue[bytecount] == 0){
      bytelengths[bytecount] = 8;
    }
    if(bytebinvalue[bytecount] == 1){
      bytelengths[bytecount] = 16;
    }
   
    bytecount = bytecount + 1;
  }
 
  for(int i = 0; i<8; i++){
    bytebinvalue[i] = 0;
  }
}

void sendbyteloop(){
  bytecount = 0;
  givelength();
  if(sfirsttime == 0){
  while(bytecount < 8){
   
    if(bytecount < 8){
      digitalWrite(Sendpin, HIGH);
      delay(bytelengths[bytecount]);
     
    }

    if(bytecount < 8){
      digitalWrite(Sendpin, LOW);
      delay(bytelengths[bytecount]);
     
      }
    }
bytecount = 0;
for(int i = 0; i<8; i++){
    bytelengths[i] = 0;
  }
  }
 
  firsttime = 1;
}



Recieve:

Code:
int Recievepin = 0;
int Sendpin = 1;
int Longcount = 0;

int firsttime = 1;
int sfirsttime = 1;
int bytepos = 0;
int bytelengths[8] = {
  0, 0, 0, 0, 0, 0, 0, 0};
int bytebinvalue[8] = {
  0, 0, 0, 0, 0, 0, 0, 0};
int bytecount = 0;
byte change0 = 0;
byte change1 = 0;
byte calcdat = 0;
byte recievelength0 = 0;
byte recievelength1 = 0;

int datar = 0; /////////This is the variable that can be transmitted using a copy of the code on a corresponding microcontroller asign actions to values for transmission
int datas = 0; /////////This is the variable that can be sent to a corresponding microcontroller with a copy of the code asign values to actions for reception

/////////////////////////////////////////////////

void setup(){
  pinMode(Recievepin, INPUT);
  pinMode(Sendpin, OUTPUT);
}

void loop(){
  delay(1);
  //commands to recieve data
    byteloop();
    if(firsttime == 0){
      lengthofvaluebuffer();
      asignvalue();
    }
  }

  //commands to send data


//////////////////////////////////////////////////

//functions for recieving data
void measurelength(){
  int Longcountdef;
  int recievelength0;
  int recievelength1;
  if(digitalRead(Recievepin == HIGH)){
    Longcount = Longcount + 1;
    delay(1);
    recievelength0 = 1;
  }
 
  if(digitalRead(Recievepin == LOW) && recievelength0 == 1){
    recievelength1++;
  }

  if(digitalRead(Recievepin == HIGH) && recievelength1 > 20){
    Longcountdef++;
  }
  if(Longcountdef * 1.1 > Longcount > Longcountdef * 0.9){
    firsttime = 0;
  }
 
 
}

void byteloop(){
  measurelength();
  if(firsttime == 0){
    while(bytecount < 8){

      while(digitalRead(Recievepin == HIGH) && bytecount < 8){
        bytelengths[bytecount] = bytelengths[bytecount] + 1;
        delay(1);
        if(change1 = 1){
          bytecount = bytecount + 1;
        }
        change0 = 1;
        change1 = 0;
      }

      while(digitalRead(Recievepin == LOW) && bytecount < 8){
        bytelengths[bytecount] = bytelengths[bytecount] + 1;
        delay(1);
        if(change0 = 1){
          bytecount = bytecount + 1;
        }
        change1 = 1;
        change0 = 0;
      }
    }
    bytecount = 0;

  }
}

void lengthofvaluebuffer(){
  bytecount = 0;
  while(bytecount < 8){
    if(bytelengths[bytecount] < Longcount * 0.7){
      bytebinvalue[bytecount] = 0;
    }
    if(bytelengths[bytecount] >= Longcount * 0.7){
      bytebinvalue[bytecount] = 1;
    }

    bytecount = bytecount + 1;
  }

  for(int i = 0; i<8; i++){
    bytelengths[i] = 0;
  }
}

void asignvalue(){
  for(int i = 0; i<8; i++)
  {
    if(bytebinvalue[i] == 1){
      datar = datar + 2^i;
    }
    else{
      datar = datar;
    }
  }
  for(int i = 0; i<8; i++){
    bytelengths[i] = 0;
  }

  firsttime = 1;
}
// above are the functions for recieving data

// below are the functions for sending data (removed from this version)
 

Harald Kapp

Moderator
Moderator
Nov 17, 2011
13,700
Joined
Nov 17, 2011
Messages
13,700
An algorithmic description instead of code would make understanding the protocoll a lot easier.

While I by no means want to disencourage you, there are a lot of rather simple serial protocols in the wild. Some wel-known ones being SPI, I²C or UART. For each of them you will find off-the-shelf code. A good example is this software-UART using only 32 words.

A proprietary protocol may have its advantages in terms of suitability to a special task. Using a standard protocol, on the other hand, has the advantage of much better support (from the community, by existing products etc.). Do you realize how many modules (e.g. GSM, GPS, accelerometer, DMX etc.) can be talked to using the UART protocol?
 

Anon_LG

Jun 24, 2014
453
Joined
Jun 24, 2014
Messages
453
OK, I see what you mean.

The link you have provided is excellent, I can actually understand that one.

I will develop a program following the diagram on the site you have provided.

Thankyou for your help Harald Kapp
 

Anon_LG

Jun 24, 2014
453
Joined
Jun 24, 2014
Messages
453
I am updating the code and will be testing it shortly, I want to keep the protocol 1-wire, I am re-writing the code altogether.
 

Anon_LG

Jun 24, 2014
453
Joined
Jun 24, 2014
Messages
453
I have simplified the code and have fixed what appeared to be the problem, which was the conversion of the int to the string and the string to int, I have used the itoa() and atoi() functions to carry out the process correctly. I am currently using micro-seconds as the time steps, this may however be too fast for the 1mhz attiny to handle. I will carry out the physical test soon. I have also succeeded in reducing the flash memory consumption greatly.

Below: The send code, taking up only 966 bytes
Code:
int longlength = 0;
int sendpin = 2;
char bits[8] = {
  0,0,0,0,0,0,0,0
};
int datas = 100;
int multi = 0;


void setup(){
  pinMode(sendpin, OUTPUT);
}

void loop(){
   
datasend();

     
}


void datasend(){
itoa(datas,bits,2); //Convert datas to a string using base 2 and save it in the array named bits
  for(int i = 0; i < 8; i++){
    if(bits[i] == 1){
      bits[i] = 16;
    }
    if(bits[i] == 0){
      bits[i] = 8;
    }
  digitalWrite(sendpin, HIGH);
  delayMicroseconds(32);
  digitalWrite(sendpin, LOW);
  for(int i = 0; i < 8;){
    digitalWrite(sendpin, LOW);
    delayMicroseconds(bits[i]);
    digitalWrite(sendpin, HIGH);
    delayMicroseconds(bits[i]);
    i++;
  }  
  }
  }

Below: The recieve code taking up only 1636 bytes
Code:
int longcount = 0;
int recievepin = 2;
int ledpin = 3;
char bits[8] = {
  0,0,0,0,0,0,0,0
};
int datar = 0;
int multi = 0;
int n;



void setup(){
  pinMode(recievepin, INPUT);
}

void loop(){
  datarecieve(); 
  binary_decimal;
  if(datar > 90){
    digitalWrite(ledpin, HIGH);
  }
  if(datar < 90){
    digitalWrite(ledpin, LOW);
  }
  }
  void datarecieve(){
     while(digitalRead(recievepin) == HIGH){
    longcount++;
    delayMicroseconds(1);
    multi = 1;
  }
  if(multi == 1){
    if(digitalRead(recievepin) == LOW && longcount > 25){
      multi = 2;
    }
  }
  if(multi == 2){
    for(int i = 0; i < 8;){
    while(digitalRead(recievepin) == LOW && multi == 7){
      bits[i] = bits[i]++;
      multi = 6;
      delayMicroseconds(1);
      i++;
    }
    delayMicroseconds(bits[i]);
    while(digitalRead(recievepin) == HIGH && multi == 6){
      bits[i] = bits[i]++;
      multi = 7;
      delayMicroseconds(1);
      i++;
    }
  }
  }
  for(int i = 0; i < 8; i++){
    if(bits[i] >= 0.3*longcount){
      bits[i] = 1;
    }
    if(bits[i] < 0.3*longcount){
      bits[i] = 0;
    }
  }
  }
int binary_decimal(int n) /* Function to convert binary to decimal.*/

{
    int decimal=0, i=0, rem;
    while (n!=0)
    {
        rem = n%10;
        n/=10;
        decimal += rem*pow(2,i);
        ++i;
    }
    return decimal;
    datar = decimal;
}

I may be able to test it tonight.
 
Last edited:
Top