As we move forward, we could really benefit from a better text editor than IDLE to edit our Python Code. In today’s lesson I show you how to download and install Pyscripter, which will make your python coding much easier. I suggest you follow these instructions and move to Pyscripter, as I will be using it for future lessons.
Category Archives: Arduino 9-Axis IMU Totorials
9-Axis IMU LESSON 15: Dynamic 3D Visualizations in Vpython
In this lesson we show you how to animate, or bring your Vpython objects to life by changing their parameters dynamically. In later lessons we will do this via life readings from sensors.
9-Axis IMU LESSON 14: Introduction to Animating Objects in Vpython
In this lesson we need to become more comfortable working with objects in Vpython. WE will show how to create an animated thermometer using the simple commands we have already learned.
9-Axis IMU LESSON 13: Introduction to Visual Python (Vpython)
In this lesson we show you how to install Visual Python (Vpython) and show you how to begin to build 3D visuals. We introduce you to some of the basic objects and how how control how they look and where they are.
9-Axis IMU LESSON 12: Passing Data From Arduino to Python
In this lesson we show how to pass data from Arduino to Python using a Com Port. This is important for our 9-Axis IMU project as we want to take advantage of the processing power and 3D graphics capabilities of Python. Our goal is to get the date from Arduino to Python, and then create a dynamic 3D visualization of our system. The first step in this goal is to pass the data from arduino to Python.
In order to do this, a first step is to install the pyserial library. If you followed our python installation tutorial in lesson 11, then it is easy to install pyserial by just opening a windows command prompt, and then typing:
pip install pyserial
If this does not work, likely you did not install python according to the instruction in lesson 11.
In order to show a simple demonstration of passing data, we can use the following code on the arduino side, which just generates x, y, and z numbers and passes them to Python.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | int x=0; int y=0; int z=0; void setup() { // put your setup code here, to run once: Serial.begin(115200); } void loop() { // put your main code here, to run repeatedly: x=x+1; y=y+2; z=z+4; Serial.print(x); Serial.print(","); Serial.print(y); Serial.print(","); Serial.println(z); delay(100); } |
We can grab these numbers from the Com port on the Python side with the following code. Note that you should use the com port your arduino is on, which likely will not be the same as mine (which was ‘com5’).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | import time import serial arduinoData=serial.Serial('com5',115200) time.sleep(1) while (True): while (arduinoData.inWaiting()==0): pass dataPacket = arduinoData.readline() #reply dataPacket=str(dataPacket,'utf-8') print(dataPacket) splitPacket=dataPacket.split(",") print (splitPacket) X=float(splitPacket[0]) Y=float(splitPacket[1]) Z=float(splitPacket[2]) print ("X=",X," Y=",Y," Z=",Z) |
The above example is just a simple method for passing different channels from Arduino to Python.
For our IMU project, we want to use the code we left off with Lesson 10. However, note we can scale back on the number of data channels, because we just want the calibration data and then the final roll, pitch and yaw numbers. This is the arduino code that will pass those parameters.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 | #include <Wire.h> #include <Adafruit_Sensor.h> #include <Adafruit_BNO055.h> #include <utility/imumaths.h> #include <math.h> float thetaM; float phiM; float thetaFold=0; float thetaFnew; float phiFold=0; float phiFnew; float thetaG=0; float phiG=0; float theta; float phi; float thetaRad; float phiRad; float Xm; float Ym; float psi; float dt; unsigned long millisOld; #define BNO055_SAMPLERATE_DELAY_MS (100) Adafruit_BNO055 myIMU = Adafruit_BNO055(); void setup() { // put your setup code here, to run once: Serial.begin(115200); myIMU.begin(); delay(1000); int8_t temp=myIMU.getTemp(); myIMU.setExtCrystalUse(true); millisOld=millis(); } void loop() { // put your main code here, to run repeatedly: uint8_t system, gyro, accel, mg = 0; myIMU.getCalibration(&system, &gyro, &accel, &mg); imu::Vector<3> acc =myIMU.getVector(Adafruit_BNO055::VECTOR_ACCELEROMETER); imu::Vector<3> gyr =myIMU.getVector(Adafruit_BNO055::VECTOR_GYROSCOPE); imu::Vector<3> mag =myIMU.getVector(Adafruit_BNO055::VECTOR_MAGNETOMETER); thetaM=-atan2(acc.x()/9.8,acc.z()/9.8)/2/3.141592654*360; phiM=-atan2(acc.y()/9.8,acc.z()/9.8)/2/3.141592654*360; phiFnew=.95*phiFold+.05*phiM; thetaFnew=.95*thetaFold+.05*thetaM; dt=(millis()-millisOld)/1000.; millisOld=millis(); theta=(theta+gyr.y()*dt)*.95+thetaM*.05; phi=(phi-gyr.x()*dt)*.95+ phiM*.05; thetaG=thetaG+gyr.y()*dt; phiG=phiG-gyr.x()*dt; phiRad=phi/360*(2*3.14); thetaRad=theta/360*(2*3.14); Xm=mag.x()*cos(thetaRad)-mag.y()*sin(phiRad)*sin(thetaRad)+mag.z()*cos(phiRad)*sin(thetaRad); Ym=mag.y()*cos(phiRad)+mag.z()*sin(phiRad); psi=atan2(Ym,Xm)/(2*3.14)*360; Serial.print(accel); Serial.print(","); Serial.print(gyro); Serial.print(","); Serial.print(mg); Serial.print(","); Serial.print(system); Serial.print(","); Serial.print(theta); Serial.print(","); Serial.print(phi); Serial.print(","); Serial.println(psi); phiFold=phiFnew; thetaFold=thetaFnew; delay(BNO055_SAMPLERATE_DELAY_MS); } |
Then, on the Python side we can grab and parse the data with this code.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | import serial import time arduinoData=serial.Serial('com5',115200) time.sleep(1) while (1==1): while (arduinoData.inWaiting()==0): pass dataPacket=arduinoData.readline() dataPacket=str(dataPacket,'utf-8') splitPacket=dataPacket.split(',') Acal=float(splitPacket[0]) Gcal=float(splitPacket[1]) Mcal=float(splitPacket[2]) Scal=float(splitPacket[3]) Pitch=float(splitPacket[4]) Roll=float(splitPacket[5]) Yaw=float(splitPacket[6]) print("Acal=",Acal,"Gcal=",Gcal,"Mcal=",Mcal,"Scal",Scal, "Pitch=",Pitch,"Roll=",Roll,"Yaw=",Yaw) |
In the next lesson we will install Vpython and begin building our code to create dynamic 3D visualizations of our system.