Timers conflicting?

I’m using my mega 1280 to take data from a bus simulator game on the pc, and run lights and gauges on a real dashboard,

I’ve just added a LCD to the board, and seem to have hit problems with the timers conflicting… i think,

Basically some code was added to stop the lcd constantly updating making it flash, and the gauges now react slowly and jerky, as if they are running in something like 4 bit mode, i.e. only a few steps from empty to full.

i ‘think’ this code that stops the lcd updating until a new value is present has caused the problem, but i could well be wrong,

My script is in my next post, as i exceed the character limit for a single post, can someone who knows more about this than me have a quick read and point out my probably simple error :slight_smile:

The script:

// Last updated: September 22th, 2013
// Using state machine pattern - based on Nick Gammon code


#include <LiquidCrystal.h>  //LCD library
#include <stdio.h>
#include <stdlib.h>

typedef enum {  NONE, GOT_I, GOT_O, GOT_R, GOT_o, GOT_T, GOT_S, GOT_B, GOT_H, GOT_b, GOT_h, GOT_P, GOT_F, GOT_A, GOT_W, GOT_V, GOT_w, GOT_r, GOT_k, GOT_a, GOT_t } states;
states state = NONE;
unsigned int currentValue;
unsigned int lastLCDMessage;

LiquidCrystal lcd(54, 55, 56, 57, 58, 59); //connections to the lcd

void setup ()
{
  Serial.begin (115200); //start serial comms
  TCCR4B = (TCCR4B & 0xF8) | 0x01 ; //adjust one of the timers to allow higher frequancy pwm for gauges
  state = NONE;
  lastLCDMessage = 998;
  pinMode(2, OUTPUT); //back lights
  pinMode(22, OUTPUT); //Light, Bus stop brakes
  pinMode(23, OUTPUT); //Switch, fan speed 3
  pinMode(24, OUTPUT); //Light, Buggy
  pinMode(25, OUTPUT); //Switch, heated mirrors
  pinMode(26, OUTPUT); //Light, Rear doors open
  pinMode(27, OUTPUT); //Switch Light, orange switch blank
  pinMode(28, OUTPUT); //Light, stop request
  pinMode(29, OUTPUT); //Switch, Rear fog
  pinMode(30, OUTPUT); //Not connected/bulb blown
  pinMode(31, OUTPUT); //Switch, Direct retarder
  pinMode(32, OUTPUT); //Light, Green dot circle
  pinMode(33, OUTPUT); //Switch, Gear D
  pinMode(34, OUTPUT); //Light, Inicators
  pinMode(35, OUTPUT); //Switch, Gear N
  pinMode(36, OUTPUT); //Light, High beam
  pinMode(37, OUTPUT); //Switch, cabin lights, 3rd in row
  pinMode(38, OUTPUT); //Light, Low oil Pressure
  pinMode(39, OUTPUT); //Switch, Buggy/rear door open
  pinMode(40, OUTPUT); //Light, Low air
  pinMode(41, OUTPUT); //Switch, School bus
  pinMode(42, OUTPUT); //Light, Brake warning
  pinMode(43, OUTPUT); //Switch, Gear, R
  pinMode(44, OUTPUT); //Light, Parking brake
  pinMode(45, OUTPUT); //Switch, Heated window?
  pinMode(46, OUTPUT); //Light, Bendy bus turning too tight
  pinMode(47, OUTPUT); //Switch, Heated side window
  pinMode(48, OUTPUT); //Light, Low coolant
  pinMode(49, OUTPUT); //Switch, Cabin lights, 4th in row
  pinMode(50, OUTPUT); //Light, High gear oil
  pinMode(51, OUTPUT); //Switch, Right hand front door
  pinMode(52, OUTPUT); //Light, Battery/no charge
  pinMode(53, OUTPUT); //Switch, Left hand front door
  //pins 54 to 59 used for LCD in ticket printer
  pinMode(60, OUTPUT); //Light, ASR
  pinMode(61, OUTPUT); //not working
  pinMode(62, OUTPUT); //not working
  pinMode(63, OUTPUT); //Light, Steering wheel with brake pads??
  pinMode(64, OUTPUT); //Light, ABS
  pinMode(65, OUTPUT); //not working
  pinMode(66, OUTPUT); //Switch, Hazards
  pinMode(67, OUTPUT); //Switch, Cabin lights, 2nd in row
  pinMode(68, OUTPUT); //Switch, Drivers cabin light, 1st in row
  pinMode(69, OUTPUT); //Switch, Park heater

lcd.begin(20, 1); // Specify how many columns and rows in the LCD unit
} 

// Lights

void Read_BusStopLight(const unsigned int value)
{
  if (value == 1)
  {
        digitalWrite(28,HIGH);  //stop request light
  }
  else
  {
        digitalWrite(28,LOW);
  }
}

void Read_Blinker(const unsigned int value)
{
  if (value == 1)
  {
        digitalWrite(34,HIGH);  //indicators
  }
  else
  {
        digitalWrite(34,LOW);
  }
}

void Read_Highbeam(const unsigned int value)
{
  if (value == 1)
  {
        digitalWrite(36,HIGH);  //highbeam
  }
  else
  {
        digitalWrite(36,LOW);
  }
}

void Read_Battery(const unsigned int value)
{
  if (value == 1)
  {
        digitalWrite(52,HIGH);  //no charge warning light
  }
  else
  {
        digitalWrite(52,LOW);
  }
}

void Read_Handbrake(const unsigned int value)
{
  if (value == 1)
  {
        digitalWrite(44,HIGH);  //parking brake warning
  }
  else
  {
        digitalWrite(44,LOW);
  }
}

void Read_LowPressure(const unsigned int value)
{
  if (value == 1)
  {
        digitalWrite(40,HIGH);  //low air pressure warning
  }
  else
  {
        digitalWrite(40,LOW);
  }
}

void Read_ABS(const unsigned int value)
{
  if (value == 1)
  {
        digitalWrite(64,HIGH);  //ABS light
  }
  else
  {
        digitalWrite(64,LOW);
  }
}

void Read_RearDoor(const unsigned int value)
{
  if (value == 1)
  {
        digitalWrite(26,HIGH);  //rear door open light
  }
  else
  {
        digitalWrite(26,LOW);
  }
}

void Read_RetarderDirect(const unsigned int value)
{
  if (value == 1)
  {
        digitalWrite(31,HIGH);  //retarder switch light
  }
  else
  {
        digitalWrite(31,LOW);
  }
}

void Read_FourFlasher(const unsigned int value)
{
  if (value == 1)
  {
        digitalWrite(66,HIGH); //hazard flashers
  }
  else
  {
        digitalWrite(66,LOW);
  }
}

void Read_Backlight(const unsigned int value)
{
  if (value == 1)
  {
        digitalWrite(2,HIGH);  //instrument back lighting
  }
  else
  {
        digitalWrite(2,LOW);
  }
}

void Read_ASR(const unsigned int value)
{
  if (value == 1)
  {
        digitalWrite(60,HIGH);  //ASR light
  }
  else
  {
        digitalWrite(60,LOW);
  }
}

// Gauges

void Read_Temperature(const unsigned int value)
{
  analogWrite(13,map(value,0,100,0,215));
}

void Read_Rpm(const unsigned int value)
{
  tone(9, map(value,0,5700,55,423));  //rev counter
}

void Read_Oil(const unsigned int value)
{
  analogWrite(11,map(value,0,50,245,0));  //oil pressure
}

void Read_Fuel(const unsigned int value)
{
  analogWrite(12,map(value,0,100,0,0235));  //fuel level
}

void Read_Velocity(const unsigned int value)
{
  tone(10, map(value,0,1250,55,423));  //speedotachograph
}

// LCD

void Read_Ticket(const unsigned int value)
{
  if (value == lastLCDMessage)
  {
      // does nothing, avoids refreshing LCD with same message
  }
  else
  {
      // refreshes LCD
	lastLCDMessage = value;
  switch (value)
  {
  	case 999:
		lcd.clear();
		lcd.print ("Druckt...");
		break;
  	case 998:
		lcd.clear();		
		break;
  	case 0:
		lcd.clear();
		lcd.print ("Fahrschein Nor :2.70");
		break;
  	case 1:
		lcd.clear();
		lcd.print ("Kurzstr Norm : 1.70");
		break;
  	case 2:
		lcd.clear();
		lcd.print ("Tageskarte Nor :9.00");
		break;
  	case 3:
		lcd.clear();
		lcd.print ("Fahrschein Erm :1.70");
		break;
  	case 4:
		lcd.clear();
		lcd.print ("Kurzstr Erm : 1.20");
		break;
  	case 5:
		lcd.clear();
		lcd.print("KuDamm-Ticket : 1.00");
		break;
  	case 6:
		lcd.clear();
		lcd.print ("Tageskarte Erm :5.00");
		break;
  	case 7:
		lcd.clear();
		lcd.print ("Komb-Tageskarte:15.00");
		break;
  	case 8:
		lcd.clear();
		lcd.print ("Tageskarte Fam:10.00");
		break;
  	case 9:
		lcd.clear();
		lcd.print ("Komb-Tagesk Erm:7.00");
		break;
	default:
		lcd.clear();
		lcd.print ("I received an unexpected value.");
  }
  }
}

void handlePreviousState()
{
  switch (state)
  {
  case GOT_R:
    Read_Rpm(currentValue);
    break;
  case GOT_o:
    Read_Oil(currentValue);
    break;
  case GOT_T:
    Read_Temperature(currentValue);
    break;
  case GOT_S:
	Read_BusStopLight(currentValue);
	break;
  case GOT_B:
	Read_Blinker(currentValue);
	break;
  case GOT_H:
	Read_Highbeam(currentValue);
	break;
  case GOT_b:
	Read_Battery(currentValue);
	break;
  case GOT_h:
	Read_Handbrake(currentValue);
	break;
  case GOT_P:
	Read_LowPressure(currentValue);
	break;
  case GOT_F:
	Read_Fuel(currentValue);
	break;
  case GOT_A:
	Read_ABS(currentValue);
	break;
  case GOT_W:
	Read_RearDoor(currentValue);
	break;
  case GOT_V:
	Read_Velocity(currentValue);
	break;
  case GOT_w:
	Read_FourFlasher(currentValue);
	break;
  case GOT_r:
	Read_RetarderDirect(currentValue);
	break;
  case GOT_k:
	Read_Backlight(currentValue);
	break;
  case GOT_a:
	Read_ASR(currentValue);
	break;
  case GOT_I:
	digitalWrite(23,HIGH);
	break;
  case GOT_O:
	digitalWrite(23,LOW);
	break;
  case GOT_t:
	Read_Ticket(currentValue);
	break;
  }
  currentValue = 0; 
}

void processIncomingByte (const byte c)
{
  if (isdigit (c))
  {
    currentValue *= 10;
    currentValue += c - '0';
  }
  else 
  {

    handlePreviousState ();
    switch (c)
    {
    case 'I':
      state = GOT_I;
      break;
    case 'O':
      state = GOT_O;
      break;
    case 'R':
      state = GOT_R;
      break;
    case 'o':
      state = GOT_o;
      break;
    case 'T':
      state = GOT_T;
      break;
    case 'S':
      state = GOT_S;
      break;
    case 'B':
      state = GOT_B;
      break;
    case 'H':
      state = GOT_H;
      break;
    case 'b':
      state = GOT_b;
      break;
    case 'h':
      state = GOT_h;
      break;
	case 'P':
	  state = GOT_P;
	  break;
	case 'F':
	  state = GOT_F;
	  break;
	case 'A':
	  state = GOT_A;
	  break;
	case 'W':
	  state = GOT_W;
	  break;
	case 'V':
	  state = GOT_V;
	  break;
	case 'w':
	  state = GOT_w;
	  break;
	case 'r':
	  state = GOT_r;
	  break;
	case 'k':
	  state = GOT_k;
	  break;
	case 'a':
	  state = GOT_a;
	  break;
	case 't':
	  state = GOT_t;
	  break;
    default:
      state = NONE;
      break;
    }
  }  
  
}

void loop()
{
	if (Serial.available())
		processIncomingByte (Serial.read());
}

No timers are involved in writing to the LCD. Any timers used are (mis)used by your code.

None of the Read_ functions I looked at READ a thing. Why are they called Read_anything?

Clearing the LCD takes time. If that interferes with your timing, you need to stop clearing the LCD. Writing fixed length strings is one way. A space will replace whatever character was there.

Ahhh, so it shouldn't be the lcd part causing the problem then,

i'll be honest, i didn't write much of that code, i started a little bit of it, then the bloke who is writing the plugin .DLL that gets the data out of the simulator for the arduino to read had a go at writing the arduino script too,

we found it worked, so he kept at it, and i must admit i dont really understand all of it,

All i know is that the data comes out of the simulator as a bunch of letters and numbers, i.e. if 'a' is present in the data string, then the arduino turns on the pin that the 'ASR' light on the dashboard is connected to, and turns it off when 'a' is no longer present in the incoming data stream,

The gauges are given letters then values i think, so 'o34' results in the oil pressure gauge's needle pointing to 3.4 bar on the scale, which is done by driving the air core via a varying PWM signal, so simulate resistance to earth as the gauges would in the vehicle.

We can't directly read text from the simulator, so he assigned 3 digit numbers to the ticket preselection choices, modified the simulators code a little to send the code when ever the relevent text is on the simulated display, and the arduino puts the text on the real display,

We found that the display was pulsing/strobing/flashing when ever text was on it, and this was assumed to be due to the display being updated constantly, so he wrote a bit of code that stopped the display refreshing until a new text set was required, at the same time he wrote in something to clear the display when ever nothing was received,

So i guess the problem is the time taken to run the script on the arduino now? with the lcd stuff clogging it up?

void Read_Rpm(const unsigned int value)
{
  tone(9, map(value,0,5700,55,423));  //rev counter
}

void Read_Oil(const unsigned int value)
{
  analogWrite(11,map(value,0,50,245,0));  //oil pressure
}

I'm going to agree with PaulS here. The Read_Rpm plays a tone. The Read_Oil function does a write. Pretty confusing.

Ahh right, let me explain:

The tone function is a variable frequency output i believe, basically a series of pulses that vary in number but stay the same in duration?,

Which is exactly what a car's rev counter and speedometer work with, i.e. one pulse per revolution of the engine, or per rotation of the prop shaft,

Hence the speedo is fed the tone signal that varies with the speed signal numbers given to it by the simulator, it goes via a transistor to give the speedo 24 volt pulses,

The other gauges want a varying resistance to earth (float arm moving a wiper on a resistance track in the fuel tank) So i feed them again via a transistor a varying PWM signal to try and simulate this.

It works, so i haven't looked for a better way to do the same job, but it is only now i am adding more items to the dashboard that i am finding things slowing down it seems, i have 4 servo operated gauges to add next, so i wonder if they will cause problems too,

Apart from the 3 gauges that get PWM signals, the rev counter and speedo that get the tone signals, and some time soon the air pressure gauges that will get servo pulses (as the arduino dosent output a 0-12 bar air pressure output :), i removed the bourdon tubes from the air gauges, and drive the needles with sub micro servo's) The other outputs are simply on or off, working light bulbs (again via transistors as they are 24 volt bulbs) Plus of course the lcd in the ticket machine, i want to add another lcd later, and put them on an I2C connection, as i'm running out of pins rapidly.