Help reading PWM on analog input

Hi guys! I have a friend who asked me to make him an LED HDD meter for his PC. It consists of 6 bi-color LED’s. Right now I modified the bar graph code example to work how I want. At the start, all the green LED’s are lit. As the pot gets turned, it turns off a green LED and turns on a red one at the same time.

What I want to to is make it so it will read the input from the motherboard header for the HDD LED and scale the LED’s accordingly. I.E. - the more HDD activity the more green LED’s will go out and red ones go on, kinda like a VU meter.

Here’s the code I have now, I’m just not sure where to go from here.

const int sensePin = A0;
const int redledCount = 6;
const int grnledCount = 6;
int redledPins[] = {
  1, 2, 3, 4, 5, 6 };
int grnledPins[] = {
  7, 8, 9, 10, 11, 12 };

void setup() {
  for (int thisredLed = 0; thisredLed < redledCount; thisredLed++) {
    pinMode(redledPins[thisredLed], OUTPUT); }
  for (int thisgrnLed = 0; thisgrnLed < grnledCount; thisgrnLed++) {
    pinMode(grnledPins[thisgrnLed], OUTPUT); }
}

void loop() {
  int sensorReading = analogRead(sensePin);
  int redledLevel = map(sensorReading, 0, 1023, 0, redledCount);
  for (int thisredLed = 0; thisredLed < redledCount; thisredLed++) {
    if (thisredLed < redledLevel) {
      digitalWrite(redledPins[thisredLed], LOW);
    }
    else {
      digitalWrite(redledPins[thisredLed], HIGH);
    }
  }
  int grnledLevel = map(sensorReading, 0, 1023, 0, grnledCount);
  for (int thisgrnLed = 0; thisgrnLed < grnledCount; thisgrnLed++) {
    if (thisgrnLed < grnledLevel) {
      digitalWrite(grnledPins[thisgrnLed], LOW);
    }
    else {
      digitalWrite(grnledPins[thisgrnLed], HIGH);
    }
  }
}

Thanks in advance!

Don't use an analog input, because the signal you are looking at is a digital signal. You'd have to build a small filter circuit to create an analog signal.

I think you need to poll the LED state (on or off) repeatedly. Then you need to derive a number from the current and recent states of the LED. The number would represent the instantaneous 'activity level' of the LED at the current instant which would tell you which red and green LEDs to illuminate.

There are lots of different ways to derive the activity level. For example you could increment a number each time you saw the LED was on and decrement it each time you saw was off. I think you will have to do some trial and error to see what level of activity you wanted to make each LED go red. For example, you may want to use a logarithmic display so that you get some indication of very low levels of activity but can see show the activity reaching very high levels.

Just use and LM3916 ( or 4 or 5, all similar) , you can use this with a low pass filter - which is simply a resistor and capacitor, no need to an Arduino, just a two dollar chip and some LEDs.

Lots of examples on your favorite video site - this being one of them -

http://www.youtube.com/watch?v=WdodJHrG8EQ&feature=related

it even has a link to the circuit.

Duane.

rcarduino.blogspot.com

[quote author=James C4S link=topic=117313.msg882704#msg882704 date=1344131537] Don't use an analog input, because the signal you are looking at is a digital signal. You'd have to build a small filter circuit to create an analog signal. [/quote]

So I'll use digital input then.

PeterH: I think you need to poll the LED state (on or off) repeatedly. Then you need to derive a number from the current and recent states of the LED. The number would represent the instantaneous 'activity level' of the LED at the current instant which would tell you which red and green LEDs to illuminate.

There are lots of different ways to derive the activity level. For example you could increment a number each time you saw the LED was on and decrement it each time you saw was off. I think you will have to do some trial and error to see what level of activity you wanted to make each LED go red. For example, you may want to use a logarithmic display so that you get some indication of very low levels of activity but can see show the activity reaching very high levels.

Any idea how to go about this? I'm decent with beginner programming but this is a tad beyond my skill level.

DuaneB: Just use and LM3916 ( or 4 or 5, all similar) , you can use this with a low pass filter - which is simply a resistor and capacitor, no need to an Arduino, just a two dollar chip and some LEDs.

Lots of examples on your favorite video site - this being one of them -

http://www.youtube.com/watch?v=WdodJHrG8EQ&feature=related

it even has a link to the circuit.

Duane.

rcarduino.blogspot.com

Neat idea but it needs to turn LED's off while others turn on at the same time. Thanks though.

OK new problem. I switched it to a digital input rather than analog. I noticed however that the input was always high, even with zero HDD activity. It turns out my motherboard has the + side of the HDD LED high all the time and switched the GND to turn it on. How would I go about reading that kind of setup on a digital input?

Sorry to do this, but going back to the LM3916, it supports dot mode, which would give you want :wink:

Other than that, one very simple idea is to use a photo transistor and just use light as the interface - probably safer as well.

EDIT - Link -

Duane B

I don't have any LM3916's available and I don't plan on ordering them. I appreciate your suggestions but I'm trying to do with with the Arduino.

SXRguyinMA: It turns out my motherboard has the + side of the HDD LED high all the time and switched the GND to turn it on. How would I go about reading that kind of setup on a digital input?

if (pin == LOW)

instead of

if (pin == HIGH)

[quote author=James C4S link=topic=117313.msg884458#msg884458 date=1344288598]

SXRguyinMA: It turns out my motherboard has the + side of the HDD LED high all the time and switched the GND to turn it on. How would I go about reading that kind of setup on a digital input?

if (pin == LOW)

instead of

if (pin == HIGH)

[/quote]

That won't work though as it's just a ground. I tried reading it that way and it doesn't change in any way. There is no high ever present on that pin. It simply connects the ground side of the HDD LED. If it were switching the V+ side it'd work fine as it would either be off or on. However this is not the case. Now I'm not sure if all motherboards are this way or just this particular one I'm using.

You are over thinking, or not realizing how switches work (transistor or physical.)

When the mother board opens the circuit it turns off led by putting its cathode high. In this case you will read and measure a high when the led is off.

When the circuit is closed, youll measure a low. This I because the motherboard closes the switch leaving a 0v drop.

[quote author=James C4S link=topic=117313.msg884651#msg884651 date=1344306175] You are over thinking, or not realizing how switches work (transistor or physical.)

When the mother board opens the circuit it turns off led by putting its cathode high. In this case you will read and measure a high when the led is off.

When the circuit is closed, youll measure a low. This I because the motherboard closes the switch leaving a 0v drop. [/quote]

But when I test it it doesn't change. If I open the serial monitor and set it to display high or low depending on the state of the LED header's ground side it never changes. It always says that the pin is low beecause there is no voltage sensed on the pin for it to read high.

Post the code you use.

What does your multimeter say?

Here’s what I’ve currently got:

const int sensePin = 13;
const int ledCount = 6;
const int redledPins[] = {
  1, 2, 3, 4, 5, 6 };
const int grnledPins[] = {
  7, 8, 9, 10, 11, 12 };

void setup() {
  Serial.begin(9600);
  pinMode(sensePin, INPUT);
  for (int thisLed = 0; thisLed < ledCount; thisLed++) {
    pinMode(redledPins[thisLed], OUTPUT);
    pinMode(grnledPins[thisLed], OUTPUT);
  }
}

void loop() {
  int sensorReading = digitalRead(sensePin);
  int ledLevel = map(sensorReading, 0, 1023, 0, ledCount);
  for (int thisLed = 0; thisLed < ledCount; thisLed++) {
    if (thisLed < ledLevel) {
      digitalWrite(redledPins[thisLed], LOW);
      digitalWrite(grnledPins[thisLed], LOW);
    }
    else {
      digitalWrite(redledPins[thisLed], HIGH);
      digitalWrite(grnledPins[thisLed], HIGH);
    }
  }
}

Haven’t checked with a meter but if I plug the + side of the HDD LED header from the motherboard into the breadboard then hook an LED from it to ground the LED is always on, it never goes out. If I hook an LED to 3v then ground it to the - side of the HDD LED header it works as intended.

Why would you bother map() on a digitalRead()? It's only values or HIGH (1) or LOW (0).

SXRguyinMA: Haven't checked with a meter but if I plug the + side of the HDD LED header from the motherboard into the breadboard then hook an LED from it to ground the LED is always on, it never goes out. If I hook an LED to 3v then ground it to the - side of the HDD LED header it works as intended.

This is exactly what you're been advised to do. The way your HDD LED is wired up, the +ve wire is always +ve and the -ve wire is switched. When the LED os 'off' the -ve wire is isolated which means it will float up to the voltage supplied on the +ve wire. When the LED is 'on' the -ve wire is pulled down to ground which causes a voltage difference across the LED so it glows.

You need to connect the LEDs -ve wire to the Arduino. Once problem you'll have is that if it is a plain old LED (without an integrated series resister) then the voltage across it will be very low, probably not enough to trigger a digital input. In that case you'll need to connect it to an analog input and compare the measured voltage with a threshold to decide whether the LED is on or off.