Multi Voltage Sensors

Hi Guys,
I have been researching for the best and cleanest sketch for reading numerous Voltage Sensors.
It appears that using an array might be the cleanest way to read up to 8 Voltage Sensors.

At the start it sounded like an easy project to create a Uno with up to 8 Voltage Sensors to trigger a 8 channel 12 volt Relay which once triggered would light up a 12 volt LED.

Here is a very rough sketch for just one Voltage Sensor and 1 Relay.
its the first one I have ever created from scratch, any help is greatly appreciated.

int relay1 = 0;
int volt1 = A0;

float vout = 0.0;
float vin = 0.0;
float R1 = 30000.0; // resistance of R1 (100K) 
float R2 = 7500.0; // resistance of R2 (10K)
int value = 0;
void setup(){
   pinMode(volt1, INPUT);
   pinMode(relay1, OUTPUT);
   
   Serial.begin(9600);

}
void loop(){
   // read the value at analog input
   value = analogRead(volt1);
   vout = (value * 5.0) / 1024.0; 
   vin = vout / (R2/(R1+R2)); 
   if (vin<0.09) {
   vin=0.0;// Voltage reading
 
} 
if vin=1<;   
digitalWrite(relay1, HIGH);// If a reading of 1< Volts relay it triggerd

fi vin=>1;
digitalWrite(relay1,LOW);// If a reading of >1 Volts relay is not triggered

}

I have read somewhere that if you are reading multiple Voltage Sensors that its best to take an average from up to 5 reading. One thing I cant have is a lag in display of LEDs as its vital the they are triggered asap (completed project to be install into a track car)

Worse case scenario would be a voltage reading every 25 mill

How are you going to read 8 analog voltages with the Arduino Uno ?

If you buy a Arduino Leonardo, Arduino Micro, Arduino Nano, Arduino Pro Mini, Arduino Mega 2560, then you have 8 analog inputs or more. You would need 8 voltage dividers, that is a total of 16 resistors. Perhaps you need some extra components for safety, or the resistors values can choosen in a way that it is safe enough for voltage peaks.

If you use a analog input, you only have to use "analogRead()", the "pinMode(..., INPUT)" is not needed.

Using the average of a few samples is better, but first you have to make this work.

An array for the voltages is indeed the cleanest way to store the analog values. Perhaps you also need an array for the pin numbers.

My guess is that reading and testing 8 analog voltages at a rate of a few hundred times per second should be possible. That means that every channel is read every 1ms ... 10ms.

Are you sure you can do this ? Is that a real full size track car ? or a RC toy ? Using an Arduino in a car it not easy.

Hey thanks for the reply

Just a quick reply as i am not at the office. Yes it's for a full on track car. I had though since the voltage sensors are physical to digital i could use some of the digital pin that the 8 channel relay where not using.

I do have a spare mega sitting around at home and changing platform is an option as i could also run a lcd.

I am new to physical computing however i am more than happy to learn and gain a greater understanding Thank you for the reply much appreciated.

After thinking over Koepels comments I have chosen to stick it out with the UNO so I have dropped the number of Voltage Sensors to 6, inline with the analog pins. As I am still learning this platform and as I progress then I can made hardware changes to suit.

When choosing to run the analog pin as an array I am a bit confused how they can then have individual values to trigger individual relays? Does anyone have a good link for more info? other than Arduino's official wiki

Koepel's comment 'Perhaps you need some extra components for safety, or the resistors values can choosen in a way that it is safe enough for voltage peaks.'

As the system in the car in 12 volt with peek output of 14-15 volts when engine is running. I have a constant reliable 5 volt which I plan to run the arduino from. Other that the voltage sensors and relays what other resistors is Koepel pointing too?

I am still learning so excuse me if I don't make sense.

I read once that electronics for a car should be able to withstand a peak of 120V.

Make a sketch for a single voltage sensor and single relay.
You would need:

  • the pin number of the analog input, for example A0.
  • the trigger point.
  • the pin number for the relay.
    Those are three things you have to know.

To extend it for for more inputs, turn those three things into arrays, and make a for-loop that checks them one by one.

const int NUM_INPUTS = 6;
const int pinVoltInputs[] = { A0, A1, A2, A3, A4, A5 };
const int pinRelays[] = { 2, 3, 4, 5, 6, 7, 8 };
const float trigger[] = { 1.0, 1.5, 2,0, 3,0, 2,5 };


void setup() {
...


void loop() {

  for(int i=0; i<NUM_INPUTS; i++) {
    int value = analogRead ( pinVoltInputs[i] );
    float vout = ( (float) value * 5.0) / 1024.0;
    float vin = vout / (R2/(R1+R2));
    if (vin < trigger[i] ) {
      ...
    }
  }
}

Or do you use two trigger points, that part is not clear for me.

This is only an example to show how to use the arrays. I’m not writing the sketch for you, Sorry.

Thanks again for the advise Koepel it is greatly appreciated

Yes starting with 1 Voltage Sensor the UNO and 1 x 12 volt relay is where I shall starting and add onto it bit by bit to see and understand the power of Sketches.

I have been researching the use of arrays and from what I have read i know it is the best way to streamline the system.

I had one other Question which I cant seem to find a good answer to.

I am wanting to have 1 GREEN LED and 1 RED LED with the function of showing if the system is functioning without errors. So the GREEN LED would be an all systems clear and the RED LED would be showing that the system is erroring and need to be fixed.

The GREEN on sounds easy but the RED one has me scratching my head... It will be vital for this system to be functioning and I need to know if its not.

Perhaps you want to turn the red led on, as soon as one input is wrong, and turn it off if all inputs are okay.
That is hard to implement.
This is easier: Test every input and at the end turn on the red or green led. During testing an integer is used to count the bad inputs. That integer has to be made zero before the inputs are going to be tested.

int inputerror;

setup() {
  ...
}

loop() {
  ...
  
  // test sequence
  inputerror = 0;                               // start with zero errors
  for(int i=0; i<NUM_INPUTS; i++) {
    // do the tests
    ...
    if ( vin < trigger[i] ) {                 // test for wrong input voltage
      inputerror++;                          // increase error count
    }
  }

  if ( inputerror == 0) {
    // okay, no errors, turn green led on
    ...
  }
  else {
    // there was (one or more) errors !
    // turn red led on
    ...
  }

The inputerror++ ; increments that value. It is the same as: inputerror = inputerror + 1 ;

w1r3d: It appears that using an array might be the cleanest way to read up to 8 Voltage Sensors.

From what you have described, I don't see any need to put the voltage readings into an array. I suggest you simply use a variable for each reading. On the other hand an array could be good if you wish to perform computations on the set of values and/or pass the values to functions within your code. Are you simply operating individual relays depending on whether a voltage from a sensor is above a threshold?

Actually it is not essential to even use variables. As HIGH and LOW correspond with true and false, you could do something like this to operate the relay, even if some would regard it as poor coding practice (I'm assuming a digital reading of 200 corresponds to 1 volt):

digitalWrite(0,analogRead(A0)>200);

w1r3d: When choosing to run the analog pin as an array I am a bit confused how they can then have individual values to trigger individual relays?

You can't "run the analog pin as an array" but you could put the readings into an array.

w1r3d: I have read somewhere that if you are reading multiple Voltage Sensors that its best to take an average from up to 5 reading. One thing I cant have is a lag in display of LEDs as its vital the they are triggered asap (completed project to be install into a track car)

There is no need to average several readings because you have more than one sensor. You generally need to average readings if the readings vary due to noise or interference.

w1r3d: Koepel's comment 'Perhaps you need some extra components for safety, or the resistors values can choosen in a way that it is safe enough for voltage peaks.'

As the system in the car in 12 volt with peek output of 14-15 volts when engine is running. I have a constant reliable 5 volt which I plan to run the arduino from. Other that the voltage sensors and relays what other resistors is Koepel pointing too?

Although the battery voltage is unlikely to go above 15V, it is reported that you can get very much higher voltage spikes on car electrical systems. Such voltage spikes could go negative as well as positive. You need to consider protecting the Vcc power supply to your Arduino as well as the inputs and outputs.

Thanks for all the tips guys, I am making time over this weekend to smash out a prototype.

I plan on doing it in steps- 1. UNO + Voltage sensor 2. UNO + Voltage sensor + status LED 2. UNO + Voltage sensor + status LED + LED relay 3. UNO + 2 x Voltage sensor + status LED + 2 x LED relay 4. UNO + 6 x Voltage sensor + status LED + 6 x LED relay

Fingers cross it all goes smoothly and I will post as I work through my steps.

I have all the components needed its just a matter of getting the coding done as hardware is a piece of cake and will take no time.

could not help myself I had to get a start on this project.
Am I even close to making a half alright code?? I do not have the benift of having someone I can bounce ideas off.
See what you think but I know its a long long way of being finished

{
	int volt1 = A0; 				// signal from Voltage Sensor
	int relay1 = 6; 				// linked to LED1
	int relay8 = 13;				// linked to RED LED
	int relay7 = 12;				// linked to GREEN LED
	int inputerror;	
	
	
}
void setup(){
	pinMode(volt1, INPUT)
	pinMode(relay8, OUTPUT)
	pinmode(relay7, OUTPUT)
	pinMode(relay1, OUTPUT)
	
	Serial.begin(9600);
}
void loop(){

void readVolt1() 
   value = analogRead(volt1);		// read the value at analog input
   vout = (value * 5.0) / 1024.0; 
   vin1 = vout / (R2/(R1+R2)); 
   if (vin<0.09) {
   vin1 =0.0;						// Voltage reading
}
void activateRelay1() {
	if 
	vin1 =1<;   
digitalWrite(relay1, HIGH);			// If a reading of 1< Volts relay it triggerd

	else  
	vin1 =>1;
digitalWrite(relay1,LOW);			// If a reading of >1 Volts relay is not triggered
}
void errorLED() {
									// test sequence
  inputerror = 0;                  	// start with zero errors
 for(int i=0; i<volt1; i++) {
 
    								// do the tests
  
    if ( vin1 < 1[i] ) {      // test for wrong input voltage
      inputerror++;               	// increase error count
    }
  }

  if 
  	( inputerror == 0) {
    digitalWrite (relay7, HIGH)		// okay, no errors, turn green led on
   
  }
  else {
    ( inouterror == 1<) {
    digitalWrite (relay8, HIGH)
    }								// there was (one or more) errors !
    								// turn red led on
    
  }	
}

How do I turn the below into an array? Is an array non blocking as in if input1 is high and activates a LED will the rest of the inputs still be read out? Is it possible to have all inputs trigger a relay??

int analogInputPin1 = A0; // 0 - 25 voltage sensors
int analogInputPin2 = A1;
int analogInputPin3 = A2;
int analogInputPin4 = A3;
int analogInputPin5 = A4;
int analogInputPin6 = A5;
int analogInputPin7= A6;

float vout = 0.0;
float vin = 0.0;
float R1 = 30000.0; 
float R2 = 7500.0;
int value = 0;

void setup(){

   Serial.begin(9600);
}
void loop(){
   // read the value of analog Voltage inputs
   value = analogRead(analogInputPin1);
   vout = (value * 5.0) / 1024.0; 
   vin = vout / (R2/(R1+R2)); 
   
    Serial.print("INPUT1 V= ");
    Serial.println(vin,2);
    delay(100);

   value = analogRead(analogInputPin2);
   vout = (value * 5.0) / 1024.0; 
   vin = vout / (R2/(R1+R2)); 
   
    Serial.print("INPUT2 V= ");
    Serial.println(vin,2);
    delay(100);

   value = analogRead(analogInputPin3);
   vout = (value * 5.0) / 1024.0; 
   vin = vout / (R2/(R1+R2)); 
   
    Serial.print("INPUT3 V= ");
    Serial.println(vin,2);
    delay(100);

       value = analogRead(analogInputPin4);
   vout = (value * 5.0) / 1024.0; 
   vin = vout / (R2/(R1+R2)); 
   
    Serial.print("INPUT5 V= ");
    Serial.println(vin,2);
    delay(100);

       value = analogRead(analogInputPin5);
   vout = (value * 5.0) / 1024.0; 
   vin = vout / (R2/(R1+R2)); 
   
    Serial.print("INPUT5 V= ");
    Serial.println(vin,2);
    delay(100);

       value = analogRead(analogInputPin6);
   vout = (value * 5.0) / 1024.0; 
   vin = vout / (R2/(R1+R2)); 
   
    Serial.print("INPUT6 V= ");
    Serial.println(vin,2);
    delay(100);
}

w1r3d:
How do I turn the below into an array?[

Try:

float vin[6];                        // array
float R1=30000, R2=7500;             // R2 connected to ground
float vpb = (R1+R2)/R2 * 5/1024;     // volts per bit
int index;

void setup()
{
  Serial.begin(9600);
}

void loop()
{
  for(index=0 ; index<=5 ; index++ )
  {
    vin[index] = analogRead(A0+index)*vpb;
    Serial.print("Input number ");
    Serial.print(index);
    Serial.print(" voltage: ");
    Serial.println(vin[index]);
  }
  Serial.println(""); // new line
  delay(1000);
}

w1r3d:
Is an array non blocking as in if input1 is high and activates a LED will the rest of the inputs still be read out?

Each of the values stored in an array will be available to be read from the array at any time.

w1r3d:
Is it possible to have all inputs trigger a relay??

When do you want your relay to be operated? Perhaps for example if any of the 6 inputs are above 1.0 volts.

The trigger point would be 3 volts.

w1r3d:
The trigger point would be 3 volts.

Does this do what you want?

float vin[6];                        // array
float R1=30000, R2=7500;             // R2 connected to ground
float vpb = (R1+R2)/R2 * 5/1024;     // volts per bit
float vmax;
int index;

void setup()
{
  Serial.begin(9600);
}

void loop()
{
  vmax = 0;
  
  for(index=0 ; index<=5 ; index++ )
  {
    vin[index] = analogRead(A0+index)*vpb;
    if(vin[index]>vmax) vmax = vin[index];
    Serial.print("Input number ");
    Serial.print(index);
    Serial.print(" voltage: ");
    Serial.println(vin[index]);
  }
  Serial.print("Maximum voltage = ");
  Serial.println(vmax);

  if(vmax>=3.0) digitalWrite(0, HIGH);   // assuming the LED is on output 0
  
  Serial.println(""); // new line
  delay(1000);
}

There’s no point putting the voltage values into an array unless you want to do something else with them.

I am only wanting to use the voltage to trigger the relays. I was thinking about arrays as they would streamline the code and i cannot have one trigger stop another from triggering another relay.

w1r3d: I am only wanting to use the voltage to trigger the relays. I was thinking about arrays as they would streamline the code and i cannot have one trigger stop another from triggering another relay.

I showed in the code I posted that you can "streamline" the code by using a 'for' loop to read the six inputs. It may then make a lot of sense to put the readings into an array as my code demonstrates. However if I correctly understand your requirement to drive relays depending on inputs being above or below 3 volts, then that can be done within the 'for' loop so there would be no need to store the voltage readings in an array for subsequent use.

Yes Archibald you are correct as the voltage values will only be used to trigger the relays for the LEDs

Would I still be able to combine the below error code?

With the idea of having an extra 2 LEDs connected to the 8 channel Optocoupler(Red and Green) to indicate if the arduino has encountered errors or to show that it is working as programmed.
This will be important as once completed the arduino will be installed out of sight.

int inputerror;

setup() {
  ...
}

loop() {
  ...
  
  // test sequence
  inputerror = 0;                               // start with zero errors
  for(int i=0; i<NUM_INPUTS; i++) {
    // do the tests
    ...
    if ( vin < trigger[i] ) {                 // test for wrong input voltage
      inputerror++;                          // increase error count
    }
  }

  if ( inputerror == 0) {
    // okay, no errors, turn green led on
    ...
  }
  else {
    // there was (one or more) errors !
    // turn red led on
    ...
  }

w1r3d:
Yes Archibald you are correct as the voltage values will only be used to trigger the relays for the LEDs

Would I still be able to combine the below error code?

With the idea of having an extra 2 LEDs connected to the 8 channel Optocoupler(Red and Green) to indicate if the arduino has encountered errors or to show that it is working as programmed.
This will be important as once completed the arduino will be installed out of sight.

I have been struggling to understand why you want the red and green LEDs as well as individual LEDs for each of the six inputs. Am I correct in now understanding that the six LEDs will not appear on your car’s dashboard, only the red and green LEDs?

I have also been unclear why you are using 12 volt LEDs driven from relay contacts. Why not use ordinary LEDs (each with a series resistor) driven directly from your Arduino at, say, 20mA?

You now mention an optocoupler. I am not clear what that is doing.

In the code below I am assuming that you want the input voltages on analogue inputs A0 to A5 to work six relays connected to corresponding digital outputs 0 to 5.

As before, my code below finds the maximum of the six input voltages and if it’s greater than 3.0V sets an output HIGH (now changed to digital output 6). Alternatively you could count the number or errors as suggested by Koepel or just have a Boolean variable set to false initially but set to true if an error is found in the ‘for’ loop.

Note variable “vin” is no longer an array. I have removed the print statements.

float vin;                           // now not an array
float R1=30000, R2=7500;             // R2 connected to ground
float vpb = (R1+R2)/R2 * 5/1024;     // volts per bit
float vmax;
int index;

void setup()
{
}

void loop()
{
  vmax = 0;
  
  for(index=0 ; index<=5 ; index++ )
  {
    vin = analogRead(index)*vpb;
    digitalWrite(index,vin>3.0);          // will write HIGH or LOW to digital outputs 0 to 5
    if(vin>vmax) vmax = vin;
  }

  if(vmax>=3.0) digitalWrite(6, HIGH);    // assuming the red and green LEDs are on output 6
  
  delay(1000);
}

I was assuming that the red and green LEDs are both connected to digital output 6, whether or not via a relay. If not via a relay, the red LED (with series resistor) would be connected between output 6 and ground while the green LED (with series resistor) would be connected between output 6 and Vcc (i.e. 5 volts).

I am also assuming you want the same voltage threshold for each input, currently 3 volts.

Sorry for any confusion regarding the relays, voltage sensor and LEDs.

The 6 analogue input pins will be the 6 voltage sensors which are connected to the Factory sensors of the engine and chassis.

These 6 inputs each have a individual relay output on an 12 volt 8 channel octcoupler and a 12 volt LED positioned on the dash cluster. I have chosen the 12 volt relays and LEDs as they are easily found and due to the construction each to swap if found faulty. Being able to change parts in and out is vital to keep the systems functioning and troubleshoot any fault or worn out parts

Outputs 7 and 8 on the 12 volt 8 channel octcoupler will indicate the status of the arduino system itself as I will not have any lcd display. A green LED will indicate that the arduino system has power and error free. The Red LED will then indicate if there are errors within the arduino system not the car.

I hope this helps you get an idea of my reasions for the selection of parts and the format of the required code.
I will be back at the warehouse over the weekend. I look foward to combining both the last sketch from Archibald (with a little changes) and the error code of Koepel.

Archibald’s code

float vin;                           // now not an array
float R1=30000, R2=7500;             // R2 connected to ground
float vpb = (R1+R2)/R2 * 5/1024;     // volts per bit
float vmax;
int index;

void setup()
{
}

void loop()
{
  vmax = 0;
  
  for(index=0 ; index<=5 ; index++ )
  {
    vin = analogRead(index)*vpb;
    digitalWrite(index,vin>3.0);          // will write HIGH or LOW to digital outputs 0 to 5
    if(vin>vmax) vmax = vin;
  }

  if(vmax>=3.0) digitalWrite(6, HIGH);    // assuming the red and green LEDs are on output 6
  
  delay(1000);
}

Koepel’s code

int inputerror;

setup() {
  ...
}

loop() {
  ...
  
  // test sequence
  inputerror = 0;                               // start with zero errors
  for(int i=0; i<NUM_INPUTS; i++) {
    // do the tests
    ...
    if ( vin < trigger[i] ) {                 // test for wrong input voltage
      inputerror++;                          // increase error count
    }
  }

  if ( inputerror == 0) {
    // okay, no errors, turn green led on
    ...
  }
  else {
    // there was (one or more) errors !
    // turn red led on
    ...
  }

Thanks for all the help I will post pics when I have it installed.
It looks great with the gauges and LEDs