Help Understanding Arduino Program with Goal to Convert to Python

I have this code that I got from learn.parallax:

void setup()                                 
{
  Serial.begin(9600);                        
}  
 
void loop()                                  
{
  long dTime = rcTime(8);                    
 
  Serial.print("time = ");                   
  Serial.print(dTime);                       
  Serial.println(" us");                     

  delay(1000);                               // 1 second delay
}
                                             // rcTime function at pin  
long rcTime(int pin)                         // ..returns decay time
{                                            
  pinMode(pin, OUTPUT);                      // Charge capacitor
  digitalWrite(pin, HIGH);                   // ..by setting pin ouput-high
  delay(1);                                  // ..for 1 ms
  pinMode(pin, INPUT);                       // Set pin to input
  digitalWrite(pin, LOW);                    // ..with no pullup
  long time  = micros();                     // Mark the time
  
  while(digitalRead(pin) == HIGH);           
  time = micros() - time;                    // Calculate decay time
  return time;                               // Return decay time
}

It works as intended (purpose is to read a phototransistor that hooks up to a digital pin). I now want to take this code and run it on my Raspberry Pi using Python. I thought this would be simple, but it has proven to be quite the challenge for me. So I have decided to take a few steps back and work to understand each line of code so I can better work on implementing it. So here are my questions:

  1. The command "pinMode(pin,INPUT)" sets the pin as the input. The purpose of this is to discharge the capacitor. How can the pin then be set too LOW in the next line if it is an input? This is not possible in Python.

  2. The while loop in the rcTime function is confusing to me. It looks like it should be an infinite loop as once the pin is HIGH it will never exit the loop. That is exactly how this behaves in Python, but not in C++.

I understand these are two completely different languages, but it would great if I could get this running my Pi. Bonus points if anyone can actually write the above code in Python!

PS: I can post my current Python code if anyone is interested, but did not want to make the post too overwhelming.

Post the circuit attached to the input output pin.

The code appears to charge a capacitor, then wait while it discharges. The while statement waits until the voltage falls below a threshold. The changing of the pin type, charging and discharging and reading and writing all…

depend on hardware details. What hardware are you running the equivalent Python on, and to what type of I/O port are you hooking you circuitry?

Post the circuit of your experiment.

a7

Below is the circuit:


And yes that is exactly what it does, it charges and discharges the capacitor while counting the time between. The time then corresponds to more and less light. This works very well for me on an Arduino.

alto777:
Post the circuit attached to the input output pin.

The circuit has been posted above for the Arduino. It is identical to the circuit that is being used on the Raspberry Pi, which is running Raspbian. I am using the CircuitPython library to control the pins. The only difference is that instead of Pin 8 I am using Pin 18 on the Raspberry Pi.

edit, OK, I see.
Def a problem with your Python.
edit.

Okay, so you still haven’t said what I/O pin on what device will be controlled by the Python.

It’s a simple set of steps, it isn’t really a matter of translation:

make the pin an output and set it high

wait 1 millisecond.

change pin to an input, note the time

wait for the pin to appear low

compute the time elapsed sinc you noted the time

If you can’t express that in Python, you are looking for help in the wrong forum. :wink:

Post the Python you claim infinitely loops that C++ does not… if you re-read the I/O pin, the change in the condition should terminate the while, so you are doing something wrong in the Python.

a7

alto777:
Okay, so you still haven’t said what I/O pin on what device will be controlled by the Python.

I answered this in my second reply where I mentioned it is pin 18? If that does answer your question I must not be understanding it properly.

Here is my Python code.

# include CircuitPython libraries
from digitalio import DigitalInOut, Direction
from board import *
import time

port = D18


def RCtime(pin):

    #Declaring pin 18 as output
    sensor = DigitalInOut(pin)
    sensor.direction = Direction.OUTPUT   

    #Charging capacitor by setting pin to HIGH
    sensor.value = True

    #Wait for 1 millisecond
    time.sleep(0.01)

    #Declaring pin 18 as input
    sensor.direction = Direction.INPUT
    
    #Set pin to LOW
    #sensor.value = False

    #mark the time
    now = time.monotonic()

    while (sensor.value == True):
         now = time.monotonic() - now
    return now

while True:
    dTime = RCtime(port)
    print('time ' + str(dTime) + ' us')

    time.sleep(1)

And I agree that I might be on wrong forum, but it is kind of a mixture of two different languages so I decided to start here.

I did see, THX.

Are you sure that this

    while (sensor.value == True):
         now = time.monotonic() - now
    return now

Reads the I/O pin? I ask because a common mistake here is to assume that the variable you've decided to use somehow magically attaches itself to a sensor or I/O pin or whatever.

sensor.value looks like a variable. How does that variable take on the value at the pin? In the Arduino "while" condition

while(digitalRead(pin) == HIGH);

we see the digitalRead() function call, that re-reads the value on the pin. And loops into it goes LOW (well, not HIGH).

Perhaps in Python referring to sensor.value implies that something re-reads the pin, that is that it tracks. Otherwise…

what does Python look like in the act of reading an I/O pin? And are the I/O ports the same as the Arduino as far as INPUT, OUTPUT and INPUT_PULLUP are concerned?

edit: also it looks like you don't have an empty statement the way you have indented it. Python weird.

a7

mitchb705:

  1. The command "pinMode(pin,INPUT)" sets the pin as the input. The purpose of this is to discharge the capacitor. How can the pin then be set too LOW in the next line if it is an input? This is not possible in Python.

There is an internal pullup resistor on the I/0 pin, outputting HIGH to an input port activates the internal pullup, outputting LOW deactivates it.

The capacitor is discharged through the phototransistor, the input port is high-impedance.

alto777:
Are you sure that this

    while (sensor.value == True):

now = time.monotonic() - now
   return now




Reads the I/O pin? I ask because a common mistake here is to assume that the variable you've decided to use somehow magically attaches itself to a sensor or I/O pin or whatever.

First just got to say thank you for your help so far! Also I do think that this loop is my issue. I do not think this changes the I/O value the way that I want it too.

I did figure out another problem though. The code in Arduino:

pinMode(pin, INPUT);                       // Set pin to input
digitalWrite(pin, LOW);                    // ..with no pullup

This removes the internal pull-up on the Arduino. I was trying to do something similar in Python, but realized that I do not need to set pin to LOW to remove pull-up. It automatically is not enabled unless I specify. So just this line of code is enough in Python:

sensor.direction = Direction.INPUT

edit: also it looks like you don't have an empty statement the way you have indented it. Python weird.

Also not sure what you mean by this. I will update this post if I am able to get it working, but I am pretty convinced that my while loop is screwed up.

In C

while (condition)
;

will sit there until the condition is false.

The semicolon is an empty statement. All the action is in evaluating the condition, which obvsly must somehow be able to change or it won’t ever exit.

digitalRead reads the pin every time the while loops. So the while has a chance to exit.

If condition is invariant and true, you stuck spinning there.

so I just googled, try it! Anyway, here’s something that looks like it reads the pin while counting, a proxy for how much time it takes reading the pin until the pin changes

    #Count until the pin goes high
    while (GPIO.input(pin_to_circuit) == GPIO.LOW):
        count += 1

From

a7

And this is wrong no matter what

while (sensor.value == True):
         now = time.monotonic() - now
return now

I’m guessing (fun!) you really want

while (sensor.value == True):
         reread the sensor however you do it...

return time.monotony() - now

a7

So I tried the code from PiMyLifeUp and it runs, but doesn't give any results that make sense. I think this is mainly due to the fact that I am using a phototransistor and their example uses an LDR. In addition the circuit does not include any type of resistor.

I also tried your guess and I did get different output, but nothing that made any sense. I found this resource online that is pretty helpful on conversion between Arduino and CircuitPython library here. I am going to keep trying a few things, but wanted to give an update.

Why labour over an RC timed circuit that probably isn't even very accurate? I'm sure you can bias the phototransistor with a simple circuit that yields an analog output that you can read from an analog input on almost any processor.

The time to abandon an idea that "just works" is exactly when you can't make it work.

aarg:
Why labour over an RC timed circuit that probably isn't even very accurate? I'm sure you can bias the phototransistor with a simple circuit that yields an analog output that you can read from an analog input on almost any processor.

The time to abandon an idea that "just works" is exactly when you can't make it work.

That is a fair point. I do not care that if it is "very accurate" I care that I can see variations in light. So more light equates to faster charge time and less light equates to a slower charge time. Even if these values are not "accurate" I can still see there is a little change in light, some change in light, more change in light, etc. In addition, this solution is super cost effective as it is just three components. However, I am about done with this and going to move onto something else, because this is not working :cry:

I did it! Not sure if this will help anyone, but here is the code:

# include CircuitPython libraries
from digitalio import DigitalInOut, Direction
from board import *
import time

port = D17
#Declaring pin 18 as output
sensor = DigitalInOut(port)

while True:
    sensor.direction = Direction.OUTPUT   
    #Charging capacitor by setting pin to HIGH
    sensor.value = True

    #Wait for 1 millisecond
    time.sleep(0.001)

    #Declaring pin 18 as input
    sensor.direction = Direction.INPUT

    #mark the time
    now = time.monotonic()

    # wait for value to be False (transition to low input)
    while sensor.value:
        pass

    print('time ' + str(time.monotonic() - now) + ' s')

    time.sleep(1)

Nice.

Pytho has a “do nothing” that’s a bit easier to spot, pass.

It’s important to know how to do nothing sometimes.

a7

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.