portion of variable is persistant [solved]

I have a Leonardo board. I am counting pulses that are put out by a fan to measure RPM. I am using pulsein() method to do this (I know I should have used pinchange interrupts etc, but I’d like to know what my issue here). Good news is that code works as intended, but only when all the fans are connected. When fan a is disconnected, I get the following outputs:

054
755
760
==
060
755
760
==
060
745
750

I really should be getting this because the fan is disconnected:

0
755
760
==
0
755
760
==
0
745
750

BTW, I know I am just putting out pulse counts & not rpm. Also, there are no noise issues. Pin 13 listed below is not connected to fan (not connected to the led like in the leonardo).

Here is the relevant portion of the code:

int fan_a		= 4;
int fan_b		= 6;
int fan_c		= 13;

int fanspeed(int fanpin){
  unsigned long pulseDuration = pulseIn(fanpin, HIGH, 8000);
  double rpm = ((double)60 /4)/((double)  1e-6 * pulseDuration);  
  return pulseDuration;
}

 Serial.println(fanspeed(fan_a));
 Serial.println(fanspeed(fan_b));
 Serial.println(fanspeed(fan_c));
 Serial.println("==");

It seems the the last two digits for fan_a are coming from fan_c when fan_a is not connected. I am using local variables. This is driving me insane. I’d appreciate if you can look this over and see what I am doing. I have a feeling it is a real dumb mistake on my part.

If the fan is not connected then the input is floating and so you could see anything on that input.

Hmm… Good point. I do have it pulled up internally though. Perhaps the internal pull up is not strong enough?

pinMode(fan_a, INPUT);
digitalWrite(fan_a,HIGH);

Would this not help?
I can see other are using this same idea here:

ztil:
I do have it pulled up internally though.

Perhaps, rather than showing us the part of the code you think is relevant to the problem, it would be better if you showed us the whole code. (And please make sure it's your actual code, and does compile and does show the problem.)

OK, Here it is. You will not be able to compile unless you install the BiColorLED, OneWire & DallasTemperature libraries.

oops. I got this when I tried to post the code here..:
The following error or errors occurred while posting this message:
The message exceeds the maximum allowed length (9500 characters).

Here is a link: http://pastebin.com/raw.php?i=Hxe5tHW7

You're calling pulseIn(fanpin, HIGH, 8000) where fanpin is an input pin that has the internal pullup enabled and is not connected, so it'll be high permanently. The documentation for pulseIn() suggests that it should time out after 8 milliseconds and return 0 in that situation. When I run this sketch on a UNO it prints out Duration=0:

const int pin = 4;

void setup()
{
  Serial.begin(9600);
  pinMode(pin, INPUT);
  digitalWrite(pin, HIGH);
}

void loop()
{
  unsigned long duration = pulseIn(pin, HIGH, 8000);
  Serial.print("Duration=");
  Serial.println(duration);
}

Perhaps there's something else going on with your hardware which you aren't aware of.

Thanks for trying out the code PeterH.

The fan pulses are being put out by a hall sensor, and they can be noisy sometimes. I hypothesized that noise was travelling from one pin to the other.

I can try two experiments tomorrow:

  • Unplug all fans and see if I get a 0.
  • Install external pullups to see if it fixes the problem.

If there are any suggestions, please let me know.

Try running that sketch and see if you get sensible behaviour?

ztil:
oops. I got this when I tried to post the code here..:
The following error or errors occurred while posting this message:
The message exceeds the maximum allowed length (9500 characters).

How to use this forum

You can attach files, like long sketches.

When you have no fan pulsein return zero, and the next line contains a divide by zero in this case.

int fanspeed(int fanpin){
  unsigned long pulseDuration = pulseIn(fanpin, HIGH, 8000);
  double rpm = ((double)60 /4)/((double)  1e-6 * pulseDuration);  
  return pulseDuration;

So creating an unsigned long and then returning it as an int does not seem likely to give good results.

So creating an unsigned long and then returning it as an int does not seem likely to give good results.

Calculating rpm is a waste of resources, too. The results are discarded as soon as they are assigned to rpm, when rpm goes out of scope.

I found the problem and it is embarrassing. The arduino code is running fine.. I had created a multithread test application in python that would send serial commands and receive data, and the receive portion was the problem.

PeterH's nudge towards starting from a simple program led the way to finding the problem, so thank you.

Here is the python test program in case anyone wants to do do this in the future..

from random import choice
import time
from serial.tools import list_ports
from serial import *
from threading import Thread, Lock

#ser = serial.Serial('/dev/tty.usbmodem411',9600,timeout=1)

last_received = ''
lock = Lock()


def receiving(ser):
    global last_received

    buffer = ''
    while True:
        #        lock.acquire()
        #        buffer = buffer + ser.read(ser.inWaiting())
        buffer = ser.readline()
        if buffer != "":
            print buffer.rstrip()


        
def sending(ser):
    led = ['run','alarm','power','temp']
    onoff = ["0","1"]
    blink = ["0","1"]
    color = ["0","1","2","3"]
    
    while True:
        lednow = choice(led)
        onoffnow = choice(onoff)
        blinknow = choice(blink)
        colornow = choice(color)

        if lednow == "alarm":
            command = "led,alarm,"+ colornow + "," + blinknow + ","
        elif lednow == "temp":
            command = "temp,"
        else:
            command = "led," + lednow + "," + onoffnow + "," + blinknow + ","


        lock.acquire()
        print ">> " + command
        ser.write(command + '\r')
        lock.release()
        #            ser.flushOutput()
        time.sleep(1)


def fan(ser):
    while True:

        command = "fan,"
        print "fan thread: " + command
        lock.acquire()
        ser.write(command + '\r')
        lock.release()
        time.sleep(1)




if __name__ ==  '__main__':
    print list_ports.comports()
    ser = Serial('/dev/tty.usbmodem411',baudrate=9600,timeout=1)

    Thread(target=fan, args=(ser,)).start()
    Thread(target=receiving, args=(ser,)).start()
    Thread(target=sending, args=(ser,)).start()