ATtiny85 not reading voltage

hello all,

I just got my new ATtiny85 to shrink down a current project I am working on. Essentially I am presetting a voltage threshold to monitor a 12V battery and trigger a relay when it gets below the threshold. I used a simple voltage divider circuit. Please note that I know I programmed my ATtiny85 correctly because I first did it with the blink sketch on an LED, so my wiring to program it is correct. Whenever I upload this to the board, the relay just comes on and stays on, and doesn't behave as it should. :frowning: Please forgive my programming as it is probably not the most efficient and logical haha..

Is this a programming issue or a hardware issue or something else? I am trying to utilize pin 3 on the ATtiny (A3) to read the voltage from the voltage divider.

Thanks!

-Adam

float vIn = 0;
float voltage = 0;
int val = 0;
int relay = 4;

float threshold = 12.3;         // ----------------SET VOLTAGE THRESHOLD HERE------------------------



void setup() {
  // put your setup code here, to run once:
    pinMode(3, INPUT);
    pinMode(relay, OUTPUT);

    digitalWrite(relay, HIGH);
}

void loop() {
  // put your main code here, to run repeatedly:
//R1 = 9.93k  || R2 = 4.7k
    val = analogRead(3);
    vIn = map(val, 0, 1023, 0, 4.819);
    voltage = map(vIn, 0, 4.819, 0, 15);
    
    if(voltage <= threshold){
      digitalWrite(relay, LOW);
      delay(3000);
      
    }

    val = analogRead(3);
    vIn = map(val, 0, 1023, 0, 4.819);
    voltage = map(vIn, 0, 4.819, 0, 15);
    
    if( voltage > threshold){
      digitalWrite(relay, HIGH);
      delay(1000);
    }
}

The map() function uses integer math so will not generate fractions, when the math might indicate that it should do so. Fractional remainders are truncated, and are not rounded or averaged.

So these lines will have issues:

vIn = map(val, 0, 1023, 0, 4.819);
voltage = map(vIn, 0, 4.819, 0, 15);

vIn = map(val, 0, 1023, 0, 4.819);
voltage = map(vIn, 0, 4.819, 0, 15);

This will return a number from 0 to 1023
val = analogRead(3);

So why not just do the comparison on that number directly?

Thanks for the reply!

What do you mean by why not just do the comparison directly? Maybe I am not quite awake yet...but I had thought that I could only do the comparison in two steps. Is there another way to do it that will make this work?

vIn = map(val, 0, 1023, 0, 4.819);
voltage = map(vIn, 0, 4.819, 0, 15);

These are also unnecessary, as you can do it in one map, and have smaller truncation error:

voltage = map(val, 0, 1023, 0, 15);

of course, as stated above, this still wouldn't work

You can:

Calculate the threshold in terms of what the ADC would read, eg 1023*12.3/15 = 838.86 (839).

You could fix this by doing, ex, int threshold = 0.5+(1023*12.3/15); the numbers will be type promoted per the usual c rules of math, then truncated when stuffed into the int.
Compare the the reading with that threshold.

Another approach is to to represent volts as millivolts instead, so instead of mapping from 0~4.819, you're mapping from 0~4819...

Thanks for the reply! Oh duh! Doing it in one map makes more sense but I see how that wouldn't work..

Thanks so much for all of that, I will give it a try!

All working now! Thanks again!