Reading Serial and Printing to LCD

Hi

I am almost getting close to finishing the programming for my final year Project at University. I am making a Wireless winch controller that will hopefully operate multiple winches on an offroad vehicle. I am using two Arduino Uno boards that are linked together via an RF link,

Transmitt board has got a input from 4 push to make switched and are coded to send A, B, C etc over the serial link, the coding for this board is as follows;

const int FWinchIn = 2; // Number of Pin for Front Winch In
const int FWinchOut = 3; // Number of pin for Front Winch Out
const int RWinchIn = 4; //Number of Pin for Rear Winch In
const int RWinchOut = 5; //Number of Pin for Rear Winch Out
int FWIN = 0; //Variable input from Front Winch In
int FWOUT = 0; //Variable input from Front Winch Out
int RWIN = 0; //Variable input from Rear Winch In
int RWOUT = 0; //Variable input from Rear Winch Out

void setup() {
  Serial.begin(9600);
  pinMode(FWinchIn, INPUT); // Setting Front Winch In as an input
  digitalWrite(FWinchIn, HIGH); //Sets Front Winch In as High
  pinMode(FWinchOut, INPUT); // Setting Front Winch Out as an input
  digitalWrite(FWinchOut, HIGH); // Sets Front Winch Out as High
  pinMode(RWinchIn, INPUT); // Setting Rear Winch In as an input
  digitalWrite(RWinchIn, HIGH); //Sets Rear Winch In as High
  pinMode(RWinchOut, INPUT); // Setting Rear Winch Out as an input
  digitalWrite(RWinchOut, HIGH); // Sets Rear Winch Out as High
}

void loop(){
  FWIN = digitalRead(FWinchIn); // Reads whether Front Winch In is high or low 
  FWOUT= digitalRead(FWinchOut); // Reads whether Front Winch Out is high or low
  RWIN = digitalRead(RWinchIn); // Reads whether Rear Winch In is high or low 
  RWOUT= digitalRead(RWinchOut); // Reads whether Rear Winch Out is high or low
     
  if (FWIN == LOW) {
    Serial.println("A"); // if Front Winch In is pressed outputs A
  }
  else {
    Serial.println("B"); // if Front Winch In is not pressed outputs B
  }
  if (FWOUT == LOW) {
    Serial.println("C"); // if Front Winch Out is pressed outputs C
  }
  else{
    Serial.println("D"); // if Front Winch Out is not pressed 0utputs D
 }
  if (RWIN == LOW) {
    Serial.println("E"); // if Rear Winch In is pressed outputs E
  }
  else {
    Serial.println("F"); // if Rear Winch In is not pressed outputs F
  }
  if (RWOUT == LOW) {
    Serial.println("G"); // if Rear Winch Out is pressed outputs G
  }
  else{
    Serial.println("H"); // if Rear Winch Out is not pressed 0utputs H
}
}

The receive board has got the output to the winches on pin 3 + 4, 6 +7 (winch in / out). on pins 2 and 5 there are a reed switch that senses the direction of the winch drum and count the number of turns of rope on the drum, the programme then stops with winch operating if there is too many or too few turns of rope on the drum. I have then got an LCD display which displays the battery voltage from pin A0 and the number of turns of rope on the drum,

#include <LiquidCrystal.h>

const int FReedSwitch = 2; //Front Reed Switch, Input Pin 2
const int FIn = 3;         //Front Winch In, Output pin 3
const int FOut = 4;        //Front winch Out, Output pin 4
int FReedSw = 0;           //Variable of Front Reed Switch
int FTurncount = 20;       //Number of Turns of Rope, front
int FPrevReedSw = LOW;     //State change of Front reed switch
unsigned long FLastReedSw = 0; //Duration Front Reed sw has been made
const int RReedSwitch = 5; //Front Reed Switch, Input Pin 5
const int RIn = 6;         //Rear Winch In, Output pin 6
const int ROut = 7;        //Rear winch Out, Output pin 7
int RReedSw = 0;           //Variable of Rear Reed Switch
int RTurncount = 20;       //Number of Turns of Rope, Rear
int RPrevReedSw = LOW;     //State change of Rear reed switch
unsigned long RLastReedSw = 0; //Duration Rear Reed sw has been made
int transInt = 50;        // transition time between bounces
int variable = 0;         //Variable is 0 unless data recieved
const int analogPin = A0;    // pin that the Potential divider is attached to
LiquidCrystal lcd (13, 12, 11, 10, 9, 8); //LCD setup

void setup() {
  Serial.begin(9600);
  pinMode(FReedSwitch, INPUT);     //Sets pin as an input
  digitalWrite(FReedSwitch, HIGH); //Pin 4 High unless Switched
  pinMode(FIn, OUTPUT);            //Sets pin as an ouput
  digitalWrite(FIn, LOW);          //Pin 5 LOW
  pinMode(FOut, OUTPUT);           //Sets pin as an output
  digitalWrite(FOut, LOW);         //Pin 6 LOW
  pinMode(RReedSwitch, INPUT);     //Sets pin as an input
  digitalWrite(RReedSwitch, HIGH); //Pin 5 High unless Switched
  pinMode(RIn, OUTPUT);            //Sets pin as an ouput
  digitalWrite(RIn, LOW);          //Pin 6 LOW
  pinMode(ROut, OUTPUT);           //Sets pin as an output
  digitalWrite(ROut, LOW);         //Pin 7 LOW
  char variable;                   //Variable is a character
  lcd.begin (16,4);                //number of lines on LCD
  lcd.print("Batt Volt=");
}

void loop(){
  FReedSw = digitalRead(FReedSwitch);
  RReedSw = digitalRead(RReedSwitch);  
  int analogValue = analogRead(analogPin);

  if( Serial.available() >0 ){ 
    variable = Serial.read(); //Read available Serial

    if (variable == 'A' && FReedSw == LOW && FPrevReedSw == LOW){
      if(millis() - FLastReedSw > transInt)
      {   
        FTurncount ++; //If Front Reed Sw and Front Winch in are made for longer
      }               //than the transition time, Count Up
      FLastReedSw = millis(); //duration of Front Reed Sw in Milliseconds
    }

    if (variable == 'C' && FReedSw == LOW && FPrevReedSw == LOW){
      if(millis() - FLastReedSw > transInt)
      {
        FTurncount --; //If Front Reed Sw and Front Winch out are made for longer
      }               //than the transition time, Count Down
      FLastReedSw =  millis(); //duration of Front Reed Sw in Milliseconds
    }
    if (variable == 'E' && RReedSw == LOW && RPrevReedSw == LOW){
      if(millis() - RLastReedSw > transInt)
      {   
        RTurncount ++; //If Rear Reed Sw and Rear Winch in are made for longer
      }               //than the transition time, Count Up
      RLastReedSw = millis(); //duration of Rear Reed Sw in Milliseconds
    }

    if (variable == 'G' && RReedSw == LOW && RPrevReedSw == LOW){
      if(millis() - RLastReedSw > transInt)
      {
        RTurncount --; //If Rear Reed Sw and Rear Winch out are made for longer
      }               //than the transition time, Count Down
      RLastReedSw =  millis(); //duration of Rear Reed Sw in Milliseconds
    }
    if(variable == 'A' && FTurncount <=30){
      digitalWrite(3, HIGH); //If A received and Turns of rope is less
    }                        //than or equal to 30 turns, Front Winch In
    else{
      digitalWrite(3, LOW);  
    }
    if(variable == 'C' && FTurncount >=10){
      digitalWrite(4, HIGH); //If C received and Turns of rope is more 
    }                        //than or equal to 10 turns, Front Winch Out
    else{
      digitalWrite(4, LOW);
    }
    if(variable == 'E' && RTurncount <=30){
      digitalWrite(6, HIGH); //If E received and Turns of rope is less
    }                        //than or equal to 30 turns, Rear Winch In
    else{
      digitalWrite(6, LOW);  
    }
    if(variable == 'G' && RTurncount >=10){
      digitalWrite(7, HIGH); //If G received and Turns of rope is more 
    }                        //than or equal to 10 turns, Rear Winch Out
    else{
      digitalWrite(7, LOW);
    }   
  }
  lcd.setCursor(10, 0); 
  lcd.print(analogValue*0.01566);
  lcd.setCursor(16,0);
  lcd.print("Front Turns = ");
  lcd.setCursor(30,0);
  lcd.print(FTurncount);
  lcd.setCursor(16,1);
  lcd.print("Rear Turns  = ");
  lcd.setCursor(30,1);
  lcd.print(RTurncount);
  
}

The problem that i have got is that as soon as i try writing anything to the LCD display there seems to be a delay in the circuit, what happens is the outputs seem to flash irregularly when the corresponding switch is pressed and there is a delay of about half a second between pressing the switch and the output operating.

Has anyone got any ideas of what would be causing this problem?

Sorry for the long post but i have tired to include as much detail as possible

Many thanks

Tris

Your sender is hammering your receiver with a steady of of "Nothing happening here" messages. Might I kindly suggest that it "Shut Up!".

The sender should only speak up if it has something to say. A, C, E, and G are useful things to send. B, D, F, and H are useless.

Might I also suggest that the compound if statements are difficult to follow. Rearrange them to use nested if statements, instead.

if(variable == 'A')
{
   if(FReedSw == LOW && FPrevReedSw == LOW)
   {
   }
}

All the stuff that should happen when an A is received should go in this if block.

The saved times get reset even when the duration is less than the interval of interest. Why is that?

Printing to an LCD takes time. Perhaps you ought not be printing on EVERY pass through loop(). Battery voltage doesn't change that often.

Since you are repositioning the cursor, writing the constant stuff every pass seems unnecessary.

PaulS:
Your sender is hammering your receiver with a steady of of "Nothing happening here" messages. Might I kindly suggest that it "Shut Up!".

The sender should only speak up if it has something to say. A, C, E, and G are usethings to send. B, D, F, and H are useless.

I understand that I am sending data that does not do anything for the programme, however I have tried to take it out and when the winch in switch is pressed it send the letter "A" but as soon as I depress the switch there is nothing reciwved that says the output should be stopped. How would I be able to stop this happening?

The programme is hard to follow as I have started with the basic switching programme and added more and more bits to the end of it as the project has developed, now you have showed me a way I can tidy it up and make it easier to follow its on my to do list.

The battery voltage is monitoring the battery of the vehicle that the winches are on, because of this it will change depending on whether the battery is being charged from the alternator or being drained by the winch. Realistically the voltage is only a guide that is useful to know so doesn't need to be displayed on every loop, how can I change it so this is the case?

Thanks for the help so far.

Tris

Look at the letters that the sender sends. All the letters from A to H are sent.

Look at the letters that the receiver pays attention to. Only A, C, G, and E cause the receiver to do anything. In many cases, any letter other than A, C, G, and E causes stuff to stop happening.

What you really need to do, I think, is to send only when there is a transition on the sender. If a switch is pressed now, but was not before, send a letter. When a switch is released now, but was not before, send the other letter in the pair. This will dramatically cut down on the volume of data sent.

I have had a go at re-working the programming on the Transmit board and it works, it constantly sends the letter 'A' while the button is pressed and stops sending 'A' when the button is depressed and the outputs on the Receive board react by operating when they should, however i am still getting a problem with the outputs flashing and a delay.

Like you have said previously it could be (and is quite probable) that i am printing to the LCD display too often, How is it possible to print to the display less often?

and it works, it constantly sends the letter 'A' while the button is pressed and stops sending 'A' when the button is depressed and the outputs on the Receive board react by operating when they should, however i am still getting a problem with the outputs flashing and a delay.

Your sender needs to send "Hey, I'm pressed" ONCE and "Hey, I was released" ONCE.

To do that, you need to keep track of the previous state of the switch.

int prevFWIN  = HIGH;
int currFWIN;

void loop()
{
   currFWIN = digitalRead(FWinchIn);
   if(currFWIN != prevFWIN)
   {
      // A transition occurred
      if(currFWIN == LOW)
      {
         // to PRESSED
      }
      else
      {
         // to RELEASED
      }
   }
   prevFWIN = currFWIN;

   // Repeat for the other 3 switches
}

As for the LCD issue, I don't know what changes, if any you have made, so, I'm reluctant to offer more advice.

I have edited the Transmit programme again so it works sending just the single letter once when the switch is pressed or released, seems to work perfectly, the code is now;

const int FWinchIn = 2; // Number of Pin for Front Winch In
const int FWinchOut = 3; // Number of pin for Front Winch Out
const int RWinchIn = 4; //Number of Pin for Rear Winch In
const int RWinchOut = 5; //Number of Pin for Rear Winch Out
int prevFWIN = HIGH;
int currFWIN;
int prevFWOUT = HIGH;
int currFWOUT;
int prevRWIN= HIGH;
int currRWIN;
int prevRWOUT = HIGH;
int currRWOUT;


void setup() {
  Serial.begin(9600);
  pinMode(FWinchIn, INPUT); // Setting Front Winch In as an input
  digitalWrite(FWinchIn, HIGH); //Sets Front Winch In as High
  pinMode(FWinchOut, INPUT); // Setting Front Winch Out as an input
  digitalWrite(FWinchOut, HIGH); // Sets Front Winch Out as High
  pinMode(RWinchIn, INPUT); // Setting Rear Winch In as an input
  digitalWrite(RWinchIn, HIGH); //Sets Rear Winch In as High
  pinMode(RWinchOut, INPUT); // Setting Rear Winch Out as an input
  digitalWrite(RWinchOut, HIGH); // Sets Rear Winch Out as High
}

void loop(){
  currFWIN = digitalRead(FWinchIn); // Reads whether Front Winch In is high or low 
  if (currFWIN != prevFWIN) {
    if(currFWIN ==LOW){   
      Serial.println("A");
    }
    else{
      Serial.println("B");
    }
    prevFWIN = currFWIN;     
  }
  currFWOUT = digitalRead(FWinchOut); //Reads whether Front Winch Out is High or LOW
  if (currFWOUT != prevFWOUT) {
    if(currFWOUT ==LOW){   
      Serial.println("C");
    }
    else{
      Serial.println("D");
    }
    prevFWOUT = currFWOUT;     
  }
  currRWIN = digitalRead(RWinchIn); // Reads whether Rear Winch In is high or low 
  if (currRWIN != prevRWIN) {
    if(currRWIN ==LOW){   
      Serial.println("E");
    }
    else{
      Serial.println("F");
    }
    prevRWIN = currRWIN;     
  }
  currRWOUT = digitalRead(RWinchOut); // Reads whether Rear Winch Out is high or low 
  if (currRWOUT != prevRWOUT) {
    if(currRWOUT ==LOW){   
      Serial.println("G");
    }
    else{
      Serial.println("H");
    }
    prevRWOUT = currRWOUT;     
  }
}

As yet i havnt made any changes to the progamme to change how often the data is written to the LCD display. I have however been thinking about how i can make it possible - Would it work if i had data written to the LCD display every second for instance rather than every loop, something like having counting the milliseconds and every time it reaches 1000 write the data to the LCD and then reset the time?

I can see in my head how it could be done but cant actually work out how to do it.

Thanks for all your help so far, it feel like im actually learning something by having to think for myself rather than copying and pasting something from the net!

I don't know if you used 'copy for forum', but that last code pretty unreadable.

Your right, I Must have pressed 'copy for forum' by mistake, I have now replaced it with the correct format. Thanks for letting me know!

I have thought of a slightly easier way to print to the LCD that sounds feasable (in my head anyway).

If i were to have a counter that counts up by one each time the void loop() completes a loop and then have an 'if' function so that when the counter reaches 10 for instance it prints the battery voltage and number of turns on the winch. I could then have another function that resets the counter to 1 every time it reaches 11.

Does this sound feasable?

Tris_C:
I have thought of a slightly easier way to print to the LCD that sounds feasable (in my head anyway).

If i were to have a counter that counts up by one each time the void loop() completes a loop and then have an 'if' function so that when the counter reaches 10 for instance it prints the battery voltage and number of turns on the winch. I could then have another function that resets the counter to 1 every time it reaches 11.

Does this sound feasable?

That would work, although you'll have to play around with the counter maximum to get it updating at your desired rate. Depending on what happens during an iteration of loop, its speed will vary a little, so the rate of LCD change will not be constant - this may not matter in this case though.

A better technique, and one that will serve you well in other projects, is your previous idea to count milliseconds. Look at the blink without delay example to see how.

In addition to widbill's comments, think about what you are writing to the LCD. Some stuff changes often. Some stuff changes slowly. Some stuff never changes.

If you write the stuff that never changes once, in setup(), and write the stuff that rarely changes only when it changes, you can write the stuff that changes often more often without negative effects.

For example, you had this code:

  lcd.setCursor(10, 0); 
  lcd.print(analogValue*0.01566);
  lcd.setCursor(16,0);
  lcd.print("Front Turns = ");
  lcd.setCursor(30,0);
  lcd.print(FTurncount);
  lcd.setCursor(16,1);
  lcd.print("Rear Turns  = ");
  lcd.setCursor(30,1);
  lcd.print(RTurncount);

These parts:

  lcd.setCursor(16,0);
  lcd.print("Front Turns = ");
  lcd.print("Rear Turns  = ");
  lcd.setCursor(30,1);

never change. Move that code to setup().

That leaves:

  lcd.setCursor(10, 0); 
  lcd.print(analogValue*0.01566);
  lcd.setCursor(30,0);
  lcd.print(FTurncount);
  lcd.setCursor(30,1);
  lcd.print(RTurncount);

The FTurncount and RTurncount values likely do not change all that often. If you keep track of the previous values written, and only write new values when the current value is different, you will have only the one line left to print on every pass through loop.

If that is too often, and it may or may not be, then you can use millis() to determine if sufficient time has passed since the last write to warrant writing again. By reducing the amount of data written at one time, you can decrease the time between writes without affecting the overall speed of the system.