Python Forum
MPU6050 +Arduino+Python
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
MPU6050 +Arduino+Python
#1
I am trying to read the output of MPU6050 connected to Arduino using Python so that I could do vibration measurement of the motor. I am able to split and also convert the string to float and get all 6 values (Ax,Ay,Az,Gx,Gy,Gz) but I'm not able to plot it using matplotlib and also the code also stops executing with some errors like:
ValueError: could not convert string to float: '1.01.05\r\n'
or
IndexError: list index out of range

import serial
import matplotlib.pyplot as ply
import numpy 
import pylab as py
from drawnow import *

ACCX=[]
ACCY=[]
ACCZ=[]
GYRX=[]
GYRY=[]
GYRZ=[]

arduinodata=serial.Serial('COM3',9600) #port name and baud rate

ply.ion()

def makeplotting():

    ply.ylabel('ACCX (°/sec)')
    ply.xlabel('Time')
    ply.plot(ACCX)


while True:
    while(arduinodata.inWaiting()==0):
        pass

    arduinostring=arduinodata.readline()
    arduinostring=str(arduinostring,encoding="utf-8")
    dataArray=arduinostring.split(',')        
    accxtemp=float(dataArray[0])
    ACCX.append(accxtemp)
    drawnow(makeplotting)
Reply
#2
Please, post full traceback in error tags.
Also - collect some sample data, as they come from arduino, without transforming them. This will help to better understand the format and also will allow to test the script (the part to parse the data)
If you can't explain it to a six year old, you don't understand it yourself, Albert Einstein
How to Ask Questions The Smart Way: link and another link
Create MCV example
Debug small programs

Reply
#3
it says the following:
Error:
Traceback (most recent call last): File "C:\Users\Meena\AppData\Local\Programs\Python\Python36\testpython1.py", line 63, in <module> accytemp=float(dataArray[1]) IndexError: list index out of range
and the other is as below:
Traceback Error


Regrading the data from Arduino, I am able to get the output after reading the line from arduino as show in this image readline from arduino
but then stops executing as shown
Error message
Reply
#4
help us to help YOU...
1. Post actual code that cause the error - your code from first post does not match the traceback you post now. The IndexError obviously is due to the fact that after split (at least for some lines) you get a 1-element tuple (i.e. the format of line is different from what you expect).
2. Don't post images - copy/paste in proper tags. Moreover your dropbox links don't work.
3. Provide some sample data
If you can't explain it to a six year old, you don't understand it yourself, Albert Einstein
How to Ask Questions The Smart Way: link and another link
Create MCV example
Debug small programs

Reply
#5
This is the code
import serial
import matplotlib.pyplot as ply
import numpy   #used for mathematical operations
import pylab as py
from mpl_toolkits.mplot3d import Axes3D
from drawnow import *

ACCX=[]
ACCY=[]
ACCZ=[]
GYRX=[]
GYRY=[]
GYRZ=[]

arduinodata=serial.Serial('COM3',9600) #port name and baud rate

fig = ply.figure()
ax = Axes3D(fig)
ply.ion()


def makeplotting():
        
        ply.subplot(611)
        ply.ylabel('ACCX (°/sec)')
        ply.xlabel('Time')
        ply.plot(ACCX)
        
        ply.subplot(612)
        ply.ylabel('ACCY (°/sec)')
        ply.xlabel('Time')
        ply.plot(ACCY)
        
        ply.subplot(613)
        ply.ylabel('ACCZ (°/sec)')
        ply.xlabel('Time')
        ply.plot(ACCZ)

while True:
        while(arduinodata.inWaiting()==0):
                pass
        arduinostring=arduinodata.readline()       
        arduinostring=str(arduinostring,encoding="utf-8")
        dataArray=arduinostring.split(',')
        accxtemp=float(dataArray[0])
        ACCX.append(accxtemp)
        accytemp=float(dataArray[1])
        ACCY.append(accytemp)
        accztemp=float(dataArray[2])
        ACCZ.append(accztemp)
        drawnow(makeplotting)
This is the error that I get
Error:
Traceback (most recent call last): File "C:\Users\Meena\AppData\Local\Programs\Python\Python36\testpython1.py", line 49, in <module> accztemp=float(dataArray[2]) IndexError: list index out of range
This is the output i get after the split i.e.,dataArray
Output:
['-0.24', '0.05', '0.91\r\n'] ['0.23', '-0.44', '1.14\r\n'] ['0.07', '0.01', '1.15\r\n'] ['0.18', '-0.12', '0.98\r\n'] ['0.12', '-0.04', '0.98\r\n'] ['0.12', '-0.03', '0.99\r\n'] ['0.11', '-0.01', '1.00\r\n'] ['0.10', '-0.02', '1.00\r\n'] ['0.11', '0.01', '1.01\r\n'] ['0.11', '-0.01', '1.00\r\n'] ['0.11', '-0.02', '0.99\r\n'] ['0.10', '-0.03', '1.01\r\n'] ['0.11', '-0.02', '1.00\r\n'] ['0.11', '-0.03', '0.99\r\n'] ['0.11', '-0.02', '1.00\r\n'] ['0.11', '-0.02', '1.00\r\n'] ['0.11', '-0.03', '1.00\r\n']
This is the outuput i get after converting it to float.
These are the values in accxtemp:
Output:
0.1 0.11 0.1 0.11 0.11 0.11 0.11 0.1 0.1 0.1 0.11 0.1 0.11 0.1 0.11 0.1 0.11 0.11 0.11 0.11 0.11 0.11 0.11 0.11 0.11 0.1
I want the output in float so that I can go ahead with plotting.
Reply
#6
So with this data, you will not get the error.
Error comes because after split() you don't have 3-element list. Obviously, from time to time, data that comes are incomplete or in slightly different format. One option would be to add an if statement right after line#44 that checks the length of dataArray is 3 before executing rest of the code in the body
One more piece of advise - collect some data in a file, just write what comes from arduino to a file, without split, plotting, etc.
take relativly large sample of data - several thousands lines at least and examine why and when you get data in different format. This will allow you to better parse the data
If you can't explain it to a six year old, you don't understand it yourself, Albert Einstein
How to Ask Questions The Smart Way: link and another link
Create MCV example
Debug small programs

Reply
#7
I have written that as you said: I think it works like that but the other problem still remains

This is my updated code below:
import serial
import matplotlib.pyplot as ply
import numpy   #used for mathematical operations
import pylab as py
from mpl_toolkits.mplot3d import Axes3D
from drawnow import *

ACCX=[]
ACCY=[]
ACCZ=[]
GYRX=[]
GYRY=[]
GYRZ=[]

arduinodata=serial.Serial('COM3',9600) #port name and baud rate

fig = ply.figure()
ax = Axes3D(fig)
ply.ion()


def makeplotting():

        ply.subplot(611)
        ply.ylabel('ACCX (°/sec)')
        ply.xlabel('Time')
        ply.plot(ACCX)
        
        ply.subplot(612)
        ply.ylabel('ACCY (°/sec)')
        ply.xlabel('Time')
        ply.plot(ACCY)
        
        ply.subplot(613)
        ply.ylabel('ACCZ (°/sec)')
        ply.xlabel('Time')
        ply.plot(ACCZ)

while True:
        while(arduinodata.inWaiting()==0):
                pass
        arduinostring=arduinodata.readline()       
        arduinostring=str(arduinostring,encoding="utf-8")
        dataArray=arduinostring.split(',')
        print (dataArray)
        if (len(dataArray)==3):
                if (type(float(dataArray[0]))is float):
                        accxtemp=float(dataArray[0])
                        ACCX.append(accxtemp)
                        print (accxtemp)
                        
                else:
                        print ('Data is not in float and hence marked to zero')
                        dataArray[0]=0.0
                        accxtemp=float(dataArray[0])
                        ACCX.append(accxtemp)
                        print (accxtemp)

                if (type(float(dataArray[1]))is float):
                        accytemp=float(dataArray[1])
                        ACCY.append(accytemp)
                        print (accytemp)
                        
                else:
                        print ('Data is not in float and hence marked to zero')
                        dataArray[1]=0.0
                        accytemp=float(dataArray[1])
                        ACCY.append(accytemp)
                        print (accytemp)

                if (type(float(dataArray[2]))is float):
                        accztemp=float(dataArray[2])
                        ACCZ.append(accztemp)
                        print (accztemp)
                        
                else:
                        print ('Data is not in float and hence marked to zero')
                        dataArray[2]=0.0
                        accztemp=float(dataArray[2])
                        ACCZ.append(accztemp)
                        print (accztemp)        
                        
                drawnow(makeplotting)        
        else:
                print ('there is some data missing')
the oupt of this is:
Output:
['0.66\r\n'] there is some data missing ['-0.72', '-0.15', '0.66\r\n'] -0.72 -0.15 0.66 ['-0.72', '-0.15', '0.66\r\n'] -0.72 -0.15 0.66 ['-0.72', '-0.15', '0.66\r\n'] -0.72 -0.15 0.66 ['-0.72', '-0.15', '0.66\r\n'] -0.72 -0.15 0.66 ['-0.72', '-0.15', '0.66\r\n'] -0.72 -0.15 0.66 ['-0.72', '-0.15', '0.66\r\n'] -0.72 -0.15 0.66 ['-0.-0.72', '-0.15', '0.66\r\n'] Traceback (most recent call last): File "C:\Users\Meena\AppData\Local\Programs\Python\Python36\testpython1.py", line 47, in <module> if (type(float(dataArray[0]))is float): ValueError: could not convert string to float: '-0.-0.72'
Error:
Traceback (most recent call last): File "C:\Users\Meena\AppData\Local\Programs\Python\Python36\testpython1.py", line 47, in <module> if (type(float(dataArray[0]))is float): ValueError: could not convert string to float: '-0.-0.72'
Reply
#8
I'm not arduino expert. Do you have explanation why you get value like -0.-0.72?
below is example how to deal with such case
import serial
import matplotlib.pyplot as ply
import numpy   #used for mathematical operations
import pylab as py
from mpl_toolkits.mplot3d import Axes3D
from drawnow import *
 
ACCX=[]
ACCY=[]
ACCZ=[]
GYRX=[]
GYRY=[]
GYRZ=[]
 
arduinodata=serial.Serial('COM3',9600) #port name and baud rate
 
fig = ply.figure()
ax = Axes3D(fig)
ply.ion()
 
 
def makeplotting():
 
        ply.subplot(611)
        ply.ylabel('ACCX (°/sec)')
        ply.xlabel('Time')
        ply.plot(ACCX)
         
        ply.subplot(612)
        ply.ylabel('ACCY (°/sec)')
        ply.xlabel('Time')
        ply.plot(ACCY)
         
        ply.subplot(613)
        ply.ylabel('ACCZ (°/sec)')
        ply.xlabel('Time')
        ply.plot(ACCZ)
        
def convert_float(value):
    try:
        return float(value)
    except ValueError:
        print ('Data {} is not in float and hence marked to zero'.format(value))
        return 0.0


while True:
    while(arduinodata.inWaiting()==0):
        pass 
    arduinostring=arduinodata.readline()       
    arduinostring=str(arduinostring,encoding="utf-8")
    dataArray=arduinostring.split(',')
    print (dataArray)
    if len(dataArray)==3:
        dataArray = list(map(convert_float, dataArray))
        # dataArray = [convert_float(v) for v in dataArray] # this is an alternative to map above
        x, y, z = dataArray
        ACCX.append(x)
        ACCY.append(y)
        ACCZ.append(z)
        drawnow(makeplotting)        
    else:
        print ('There is some data format problem: {}'.format(dataArray))
Couple of remarks:
Not sure, but could the problem with data come because you using inWaiting() and timeout?
Why do you use old version of pyserial? current version is 3.4 and inWaiting was changed to in_waiting in 3.0
it's possible to make additional changes to code to make it more readable/pythonic
If you can't explain it to a six year old, you don't understand it yourself, Albert Einstein
How to Ask Questions The Smart Way: link and another link
Create MCV example
Debug small programs

Reply
#9
The reading are from sensor. I am not really sure whats he problem with it. Hence,I wanted to convert it to 0.0 if there is such format issue.
I tried updating pyserial but says its already updated and therefore i am using inWaiting instead of in_waiting.
I am still trying to process data. I am sure that most of the issues is taken care of.
Thanks a ton for your help. I was not really sure how to do it as I am an absolute beginner to python programming.
I will post in case I have some issues further.
Have a great day ahead... :)
Reply
#10
(Mar-28-2018, 11:39 AM)MeenakshiChowdhary Wrote: tried updating pyserial but says its already updated and therefore i am using inWaiting instead of in_waiting.
strange. from the docs
Quote:in_waiting
Getter: Get the number of bytes in the input buffer
Type: int

Return the number of bytes in the receive buffer.

Changed in version 3.0: changed to property from inWaiting()
If you can't explain it to a six year old, you don't understand it yourself, Albert Einstein
How to Ask Questions The Smart Way: link and another link
Create MCV example
Debug small programs

Reply


Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020