Go Down

Topic: Wierd Serial and cpu usage. (Read 1 time) previous topic - next topic

3_141592_Co

Nov 03, 2014, 01:05 am Last Edit: Nov 03, 2014, 10:59 pm by 3_141592_Co
So I have been using opencv pretty sucessfully over the last week to do the grunt work or tracking motion but I have come upon a very wierd snag over the last two days. While trying to send multiple char's over the serial port something snags after a random amount of time normally over 15 seconds. Its is random and I have no idea whats causing it at first I thought mabye I wasn't resetting a table in the arduino and it's memory was running out and my program was just waiting for the serial to come back but then I looked at cpu usage on my laptop. It goes from 26-30% at .6gb to 100% when it snags. Another wierd thing about when it snags is both the TX and RX led's light up on the arduino so I am assuming they are sending and recieving serial? My laptop isn't reporting anything happening over serial though? That and if I press the reset button on the arduino the led's just stay on even after I kill the program on my laptop. I have to physically unplug the arduino before that stops. While it is doing the LED thing I can't re-upload the arduino either so I am assuming something is going on serially. I have been hunting around online and I think I am doing everything right but I am little confused. If someone could go over my code and help out it would be amazing. I am using python on an ubuntu 14.04 os.
Python Code.
Code: [Select]

import cv
import serial
import time
import threading
import sys


class Target:
    def __init__(self):
        self.capture = cv.CaptureFromCAM(0)
        cv.NamedWindow("Target", 1)

    def run(self):
        # Capture first frame to get size
        frame = cv.QueryFrame(self.capture)
        frame_size = cv.GetSize(frame)
        grey_image = cv.CreateImage(cv.GetSize(frame), cv.IPL_DEPTH_8U, 1)
        moving_average = cv.CreateImage(cv.GetSize(frame), cv.IPL_DEPTH_32F, 3)
        difference = None
        ser = serial.Serial("/dev/ttyACM0", 9600)
        connected = 0
        while connected == 0:
            ser.write("c") #Seeing if the arduino is open to com yet
            if ser.read() == 4: #Arduino saying it is open to com
                 connected = 1
            time.sleep(1)
        while connected == 1:
            # Capture frame from webcam
            color_image = cv.QueryFrame(self.capture)

            # Smooth to get rid of false positives
            cv.Smooth(color_image, color_image, cv.CV_GAUSSIAN, 3, 0)

            if not difference:
                # Initialize
                difference = cv.CloneImage(color_image)
                temp = cv.CloneImage(color_image)
                cv.ConvertScale(color_image, moving_average, 1.0, 0.0)
            else:
                cv.RunningAvg(color_image, moving_average, 0.020, None)

            # Convert the scale of the moving average.
            cv.ConvertScale(moving_average, temp, 1.0, 0.0)

            # Minus the current frame from the moving average.
            cv.AbsDiff(color_image, temp, difference)

            # Convert the image to grayscale.
            cv.CvtColor(difference, grey_image, cv.CV_RGB2GRAY)

            # Convert the image to black and white.
            cv.Threshold(grey_image, grey_image, 70, 255, cv.CV_THRESH_BINARY)

            # Dilate and erode to get object blobs
            cv.Dilate(grey_image, grey_image, None, 18)
            cv.Erode(grey_image, grey_image, None, 10)

            # Calculate movements
            storage = cv.CreateMemStorage(0)
            contour = cv.FindContours(grey_image, storage, cv.CV_RETR_CCOMP, cv.CV_CHAIN_APPROX_SIMPLE)
            points = []

            while contour:
                # Draw rectangles
                bound_rect = cv.BoundingRect(list(contour))
                contour = contour.h_next()

                pt1 = (bound_rect[0], bound_rect[1])
                pt2 = (bound_rect[0] + bound_rect[2], bound_rect[1] + bound_rect[3])
                points.append(pt1)
                points.append(pt2)
                cv.Rectangle(color_image, pt1, pt2, cv.CV_RGB(255,0,0), 1)

            num_points = len(points)
            if num_points:
                # Draw bullseye in midpoint of all movements
                x = y = 0
                for point in points:
                    x += point[0]
                    y += point[1]
                x /= num_points
                y /= num_points
                center_point = (x, y)
                cv.Circle(color_image, center_point, 40, cv.CV_RGB(255, 255, 255), 1)
                cv.Circle(color_image, center_point, 30, cv.CV_RGB(255, 100, 0), 1)
                cv.Circle(color_image, center_point, 20, cv.CV_RGB(255, 255, 255), 1)
                cv.Circle(color_image, center_point, 10, cv.CV_RGB(255, 100, 0), 5)
                #############serial communication###########
                ser.write("n") #checking if arduino is ready for new cordinates
                read = ser.read()
                if read == '3': #arduino saying it's ready for new cordinates
                   ser.write(str(center_point[0]))
                   time.sleep(.01)
                   ser.write(str(center_point[1]))
                   ser.read(timeout =.5)
                print(center_point[1])
                print(ser.readline(len(str(center_point[1]))+3))
               
            # Display frame to user
            cv.ShowImage("Target", color_image)

            # Listen for ESC or ENTER key
            c = cv.WaitKey(7) % 0x100
            if c == 27 or c == 10:
                break
               
if __name__=="__main__":
    t = Target()
    t.run()


Arduino Code
Code: [Select]

char myChar;
String content = "";
char character;
void setup()
{
  pinMode(5, OUTPUT);
  Serial.begin(9600);
}
void loop()
{
  //if (Serial.available())
  //{
    //myChar = Serial.read();
    //if (myChar == 'c'
    //{
     // Serial.write(4);
    //}
    //else if (myChar == '2')
    //{
    //  Serial.write(3);
    //}
    //oldData = newData; // overwrite last input
    //newData = myChar.toInt(); // fetching the new data
    //Data = newData + oldData; // keeping count of the data

  //}


  while(Serial.available()) {
      character = Serial.read();
      content.concat(character);
  }
  // myChar = Serial.read();
  if (character == 'c') // first varible saying to connect
  {
    Serial.write('4'); // just saying it's connected
  }
  else if (character == 'n') // need to change to motor control varible
  {
    Serial.write('3'); // flow varible to accept new value
  }
  if (content != "") {
    Serial.println(content);
    //delay();
  character = 0;
  content = 0; //this is a new line it adds about 1 minute longer before the the program becomes unresponsive
  }
}


Upon further reveiw of the serial monitor the Arduino sketch program has it appears the character n is being printed with twice the amount of n's as the time before so at 5600 times a second it umm gets very large very quickly and the processor is trying to catch up. I am not really sure how to fix this?

PaulS

Code: [Select]
..first open serial port and wait for arduino (not a problem already been tested extensively)
... blah blah blah doing fun maths not serial

So, the answer is pretty simple, really.

blah, blah blah.

When you post ALL of your code, we'll reveal the actual answer.
The art of getting good answers lies in asking good questions.

Robin2

I can't figure from your Post whether you are generally well able to communicate between Arduino and Python or whether this is your first project. If you are new to it, have a look at the Sticky demo at the top of this section of the Forum.

If you can normally get your comms to work you should explain what is unusual about this case.

What is opencv?

...R
Two or three hours spent thinking and reading documentation solves most programming problems.

3_141592_Co

#3
Nov 03, 2014, 08:03 pm Last Edit: Nov 03, 2014, 09:36 pm by 3_141592_Co
So to reply to your post robin I have am a little new to communication via serial but I have been able to understand all of the demos and run all of them successfully. I understand (or at least I think I do) how this all works and so far it has.

OpenCV is a library designed to help with "Computer vision" based applications. Like object detection and motion tracking.

To summarize the weird issue's I am coming into contact with is that fact that the program freeze's and cpu usage goes to 100%. This is a serial issue because it doesn't have a issue with the serial lines just commented out. Also the Arduino is still sending data after I press the reset pin and doesn't appear to be following the delays I put in place on it.

The reason why I am using a much more simple method than the one you described in your demo post is because in honesty it's pretty complicated. It confuses me and I only need to send two different numbers over serial. I can see that the program is pretty complticated and in all reality I am a complete newcomer to python.

I also in no way ment to affend anyone by not including the code previous to the code that was already posted I just figured that if I was able to narrow the amount of code that was affecting this behavoir I figured I wouldn't make it so hard for you guys. I wanted to avoid offending anyone by making them feel as if I just wanted them to look through a long stack of ill formatted code to help me.

 

Robin2

This last line
Code: [Select]
content = 0; would not compile for me so I changed it to
Code: [Select]
content = "";

What does that do for you?

My suspicion is that your code is continuously sending stuff and eventually overwhelms the PC input buffer - which would remain full even if you reset the Arduino.

...R
Two or three hours spent thinking and reading documentation solves most programming problems.

3_141592_Co

#5
Nov 03, 2014, 11:26 pm Last Edit: Nov 04, 2014, 12:26 am by 3_141592_Co
Ok Yea I know the buffer is being overflown but that means I must have made some sort of infinate loop/constantly sending something but I can't seem to find that. It's weird that it didn't compile for you lol because it did for me I will check up on that fix.

Or is that internal buffer something I need to reset every time the program loops over again? And if so how would I go about doing that?

So after looking around I found that adding the
flushInput()
flushOutput()
commands at the end of my loop works great. It doesn't lose any data because my arduino doesn't send any before my program ask for it and it helps it work fine

Robin2

Ok Yea I know the buffer is being overflown but that means I must have made some sort of infinate loop/constantly sending something but I can't seem to find that. It's weird that it didn't compile for you lol because it did for me I will check up on that fix.
I rather hoped you would check that fix before you replied because I suspect it is the cause of the constant sending.

...R
Two or three hours spent thinking and reading documentation solves most programming problems.

Go Up