1

Before I get into the background of what's going on, the problem, and the steps I've taken to fix it, here's a quick summary of the equipment I'm using for my project

Equipment I'm using:

Infrared Encoder: https://www.amazon.ca/dp/B07B3PLZZ2/ref=cm_sw_r_oth_api_glt_i_NCFT5KHJBARTBC76XG7Y?_encoding=UTF8&psc=1

Arduino Mega 2560 w/ 9V 1A power adapter: https://www.amazon.ca/gp/product/B01H4ZDYCE/ref=ppx_yo_dt_b_asin_title_o01_s00?ie=UTF8&psc=1

Computer: Macbook Pro 2020, M1 Chip, 8 GB RAM

IDE: Pycahrm Community Edition

Python Interpreter: Python 3.8

Background:

I have a fan that spins at a constant speed. Intercepting the blades of the fan is my Infrared encoder that's hooked up to my Arduino. as the blades spin through the infrared encoder, the Arduino script I wrote is supposed to print a '1' if the sensor is triggered and a '0' if it isn't.

This works fine.

Now, I want to be able to use this '1' and '0' data in Python because I have an idea for a video game I want to prototype using Pygame.

On Pycharm, I installed pyserial so I'm able to access all the data. In order to capture the 1's and 0's in Pycharm, here's the code I've written:

Variables

serialInst = serial.Serial()
serialInst.port = '/dev/cu.usbmodem11301'
serialInst.baudrate = 9600
serialInst.timeout = 0.5
serialInst.open()

Read Data Function

def readData(self):

    if serialInst.inWaiting():

        packet = serialInst.readline()

        if int(packet.decode('utf').rstrip('\n')) == 1:
            
            print('1')

        elif int(packet.decode('utf').rstrip('\n')) == 0:

            print('0')

The way it works is fairly simple. As I described before, if the fan triggers the sensor, Arduino prints out a '1', and then Python reads the data and confirms it with the if statement.

Same operation for when the sensor is not triggered.

The Problem

This function is the first function called in the main while loop of my python code. There are other functions that are called afterward before it loops around to the readData function however when those functions are called, it's almost as if the Arduino data stops checking to see if there have been any changes.

What the problem looks like

No matter if the fan's blades go through the sensor, the output is always 0

If I comment out any function that's used in the main while loop, everything works 100% fine. The issue only happens when I start to introduce other functions into the main while loop.

What I've tried

I currently have 9 other tabs open with similar Pyserial issues people have reported here on StackOverflow and here are some of the things I've read about and tried:

  • Adding a serialInst.timeout value. I played with a variety of numbers from 0.01 to 0.5 and haven't found success

  • Using serialInst.reset_output_buffer(), serialInst.flushOutput(), serialInst.reset_input_buffer(), or serialInst.flushInput() in a variety of different locations

  • And I've tried many more potential solutions however, this was when my problem was even worse... Before, I had the readData function as part of a Class in another however, every time I tried to run it from the main while loop, it would skip data, not give any data, show very odd characters... it was just a nightmare.

Now I have the readData function in the main game Class and just need to solve this last issue and everything will work.

Summary

I have a python function called readData that reads data coming from an Arduino that's either a '1' or a '0'. When the readData is the only function being called in the main while loop of my program, everything works fine; there are '1's when there should be and '0' when there should be.

The problem arises when I uncomment the other functions in the while loop that I have to use.

The program definitely loops through the entire while loop however, when it reaches the readData function, it gets "stuck" at reading just '0'... even when there's supposed to be a '1'.

What I need

The readData function if statements should print out a '1' or '0' correctly, no matter if the other functions in the main while loop are commented out or not.

I need to "unfreeze" whatever is holding up that part of the program.

Please let me know if you need any more information. I really appreciate your time.

Update

It seems as though when the other functions are called, everything works fine however, when I can pygame.display.update(), that's when the arduino data starts to "freeze".

I'm not sure why updating the screen for my game will cause the program to stop working...

I also added a Serial.flush() to the Arduino code... if that helps...

1
  • Divide and conquer - how about writing a couple of simple test programs. Forget the game you're trying to write for a moment; just focus on THIS problem. You say that you can get it to work with a main loop that has nothing else in it. Okay, show us that complete program. Now you say that if you add other functions in the loop, it doesn't work. Add some stupid little function to make a time delay, or print the time of day, or something like that. If your fan-reading function quits working, show us that program. Otherwise keep adding functions until it breaks. Then show us that. Commented Sep 15, 2021 at 5:08

1 Answer 1

2

Fixed the problem

I was wrong in thinking it was the other functions that I was calling in the while loop that caused the problem.

It turns out, when I uncommented the other functions, my code ran as expected:

There were 1's when the fan triggered the sensor and 0s when there was no sensor activity.

So what exactly was the problem?

It was a few things:

1. pygame.display.update()

When I uncommented pygame.display.update(), this is when my realData() function (the function who's job it is to output the 1's and 0's) would "freeze."

It was look like this:

0
0
0
0
0
0
0

It would never pick up a '1' even though the fan was clearly hitting the sensor.

The reason for this, I still have no idea... but I found a way past it.

To fix this, I added this:

serialInst.reset_input_buffer()

to the end of the realData() function.

After this, I was introduced to a new problem:

The data outputted 1's, 0's and a bunch of spaces I didn't want. It would look like this:

1
0
0
0
0

0

0


0

1

0

1

I didn't want those spaces because my realData() function was programmed with certain if statements that would perform certain tasks if there was a 1 OR a 0... not a newline/space.

The reason this happened was because of the Arduino.

Here's the code on the Arduino side that was causing the problem:

void loop() {
  // read the state of the pushbutton value:
  x = digitalRead(sensor);

  // check if the fan hit the sensor. If it is, the sensor is HIGH:
  if (sensor == HIGH) {
     
    Serial.print(1);

  } else {
    
    Serial.print(0);

  }

}

The problem was, I was using:

Serial.println(1)

// and

Serial.println(0)

This would tell Pycharm that I wanted to send 1's, 0's, and new lines. Therefore, I changed that code to:

Serial.print(1)

// and

Serial.print(0)

This eliminated Pycharm from receiving the random new lines

After, there was still two last issues on the Pycharm side to fix which was easy:

Instead of capturing the data in Pycharm with:

packet = serialInst.readline()

I used:

packet = serialInst.read()

The final part was to simply decode the message because it would output things like:

b'0'
b'0'
b'0'
b'1'
b'0'
b'0'

So I simply used:

x = int(packet.decode('utf'))

The final product looked like this:

0
0
0
0
0
0
0
0
1
0
0
0
0
0
0
0
0
1
0
0

Etc...

Now I can use the if statements to further progress my game depending on if a '1' is in the output or a '0'.

It's now perfect. I truly hope this helps anyone who is experiencing the same issues I was.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.