-
Notifications
You must be signed in to change notification settings - Fork 32
adding roll pitch yaw example, including processing.org sketch #4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
owennewo
wants to merge
4
commits into
arduino-libraries:master
Choose a base branch
from
owennewo:master
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 2 commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
bae11bf
adding roll pitch yaw example, including processing.org sketch
owennewo 38c4dd2
suggested changes from pull request + moved processing,org example to…
owennewo c712531
moving processing to data folder
owennewo 5eac7f5
Reduce the possibility of divide by zero error.
owennewo File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,157 @@ | ||
/** | ||
What is this file? | ||
This is an arduino example that calculates accurate roll,pitch,yaw from raw gyro/accelerometer data | ||
It has a calibration stage which removes most of the gyro drift and a complementary filter | ||
that combines gyro and accelerometer angles to produce roll/pitch angles that don't drift (like the gyro angle) and aren't noisy | ||
(like the accel angles). As there is no magnetic compass on the nano iot 33, it's not possible to 'complement' the yaw | ||
- hence yaw will drift and is 'relative'. | ||
*/ | ||
#include <Arduino_LSM6DS3.h> | ||
#include <Wire.h> | ||
|
||
float accelX, accelY, accelZ, // units m/s/s i.e. accelZ if often 9.8 (gravity) | ||
gyroX, gyroY, gyroZ, // units dps (degrees per second) | ||
gyroDriftX, gyroDriftY, gyroDriftZ, // units dps | ||
gyroRoll, gyroPitch, gyroYaw, // units degrees (expect major drift) | ||
gyroCorrectedRoll, gyroCorrectedPitch, gyroCorrectedYaw, // units degrees (expect minor drift) | ||
accRoll, accPitch, accYaw, // units degrees (roll and pitch noisy, yaw not possible) | ||
complementaryRoll, complementaryPitch, complementaryYaw; // units degrees (excellent roll, pitch, yaw minor drift) | ||
|
||
long lastTime; | ||
long lastInterval; | ||
|
||
void setup() { | ||
|
||
Serial.begin(1000000); | ||
pinMode(LED_BUILTIN, OUTPUT); | ||
|
||
// this sketch will wait until something connects to serial! | ||
// this could be 'serial monitor', 'serial plotter' or 'processing.org P3D client' (see ./processing/RollPitchYaw3d.pde file) | ||
while (!Serial); | ||
|
||
if (!IMU.begin()) { | ||
Serial.println("Failed to initialize IMU!"); | ||
while (1); | ||
} | ||
|
||
calibrateIMU(250, 250); | ||
|
||
lastTime = micros(); | ||
|
||
} | ||
|
||
/* | ||
the gyro's x,y,z values drift by a steady amount. if we measure this when arduino is still | ||
we can correct the drift when doing real measurements later | ||
*/ | ||
void calibrateIMU(int delayMillis, int calibrationMillis) { | ||
|
||
int calibrationCount = 0; | ||
|
||
delay(delayMillis); // to avoid shakes after pressing reset button | ||
|
||
float sumX, sumY, sumZ; | ||
int startTime = millis(); | ||
while (millis() < startTime + calibrationMillis) { | ||
if (readIMU()) { | ||
// in an ideal world gyroX/Y/Z == 0, anything higher or lower represents drift | ||
sumX += gyroX; | ||
sumY += gyroY; | ||
sumZ += gyroZ; | ||
|
||
calibrationCount++; | ||
} | ||
} | ||
|
||
if (calibrationCount == 0) { | ||
Serial.println("Failed to calibrate"); | ||
} | ||
|
||
gyroDriftX = sumX / calibrationCount; | ||
gyroDriftY = sumY / calibrationCount; | ||
gyroDriftZ = sumZ / calibrationCount; | ||
|
||
} | ||
|
||
/** | ||
Read accel and gyro data. | ||
returns true if value is 'new' and false if IMU is returning old cached data | ||
*/ | ||
bool readIMU() { | ||
if (IMU.accelerationAvailable() && IMU.gyroscopeAvailable() ) { | ||
IMU.readAcceleration(accelX, accelY, accelZ); | ||
IMU.readGyroscope(gyroX, gyroY, gyroZ); | ||
return true; | ||
} | ||
return false; | ||
} | ||
|
||
// the loop function runs over and over again forever | ||
void loop() { | ||
|
||
if (readIMU()) { | ||
long currentTime = micros(); | ||
lastInterval = currentTime - lastTime; // expecting this to be ~104Hz +- 4% | ||
lastTime = currentTime; | ||
|
||
doCalculations(); | ||
printCalculations(); | ||
|
||
} | ||
|
||
} | ||
|
||
/** | ||
I'm expecting, over time, the Arduino_LSM6DS3.h will add functions to do most of this, | ||
but as of 1.0.0 this was missing. | ||
*/ | ||
void doCalculations() { | ||
accRoll = atan2(accelY, accelZ) * 180 / M_PI; | ||
accPitch = atan2(-accelX, sqrt(accelY * accelY + accelZ * accelZ)) * 180 / M_PI; | ||
|
||
float lastFrequency = 1000000 / lastInterval; | ||
gyroRoll = gyroRoll + (gyroX / lastFrequency); | ||
gyroPitch = gyroPitch + (gyroY / lastFrequency); | ||
gyroYaw = gyroYaw + (gyroZ / lastFrequency); | ||
|
||
gyroCorrectedRoll = gyroCorrectedRoll + ((gyroX - gyroDriftX) / lastFrequency); | ||
gyroCorrectedPitch = gyroCorrectedPitch + ((gyroY - gyroDriftY) / lastFrequency); | ||
gyroCorrectedYaw = gyroCorrectedYaw + ((gyroZ - gyroDriftZ) / lastFrequency); | ||
|
||
complementaryRoll = complementaryRoll + ((gyroX - gyroDriftX) / lastFrequency); | ||
complementaryPitch = complementaryPitch + ((gyroY - gyroDriftY) / lastFrequency); | ||
complementaryYaw = complementaryYaw + ((gyroZ - gyroDriftZ) / lastFrequency); | ||
|
||
complementaryRoll = 0.98 * complementaryRoll + 0.02 * accRoll; | ||
complementaryPitch = 0.98 * complementaryPitch + 0.02 * accPitch; | ||
} | ||
|
||
/** | ||
This comma separated format is best 'viewed' using 'serial plotter' or processing.org client (see ./processing/RollPitchYaw3d.pde example) | ||
*/ | ||
void printCalculations() { | ||
Serial.print(gyroRoll); | ||
Serial.print(','); | ||
Serial.print(gyroPitch); | ||
Serial.print(','); | ||
Serial.print(gyroYaw); | ||
Serial.print(','); | ||
Serial.print(gyroCorrectedRoll); | ||
Serial.print(','); | ||
Serial.print(gyroCorrectedPitch); | ||
Serial.print(','); | ||
Serial.print(gyroCorrectedYaw); | ||
Serial.print(','); | ||
Serial.print(accRoll); | ||
Serial.print(','); | ||
Serial.print(accPitch); | ||
Serial.print(','); | ||
Serial.print(accYaw); | ||
Serial.print(','); | ||
Serial.print(complementaryRoll); | ||
Serial.print(','); | ||
Serial.print(complementaryPitch); | ||
Serial.print(','); | ||
Serial.print(complementaryYaw); | ||
Serial.println(""); | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,128 @@ | ||
/** | ||
* What is this file? | ||
* This is a processing.org sketch and is *NOT* loaded onto your arduino. | ||
* Instead the processing development environment runs this sketch as a 3d application on your computer. | ||
* The sketch connect to your arduino's serial port and reads the roll/pitch/yaw data and displays this | ||
* as 3d models. This sketch assumes you've loaded RollPitchYaw.ino onto your nano iot 33 (or similar) board | ||
* | ||
* License LGPL2.1+ | ||
*/ | ||
|
||
import processing.serial.*; | ||
import java.awt.event.KeyEvent; | ||
import java.io.IOException; | ||
|
||
Serial arduino; | ||
|
||
float gyroRoll, gyroPitch, gyroYaw; // units degrees (expect major drift) | ||
float gyroCorrectedRoll, gyroCorrectedPitch, gyroCorrectedYaw; // units degrees (expect minor drift) | ||
float accRoll, accPitch, accYaw; // units degrees (roll and pitch noisy, yaw not possible) | ||
float complementaryRoll, complementaryPitch, complementaryYaw; // units degrees (excellent roll, pitch, yaw minor drift) | ||
|
||
|
||
// NOTE: You need to provide or discover a portName. Often it's at a fixed index (e.g. 0, 1) in the serial list. Or you may prefer to hardcode it. Look at commented lines below for examples. | ||
//int portIndex = 0; | ||
int portIndex = 1; | ||
|
||
String portName = Serial.list()[portIndex]; | ||
//String portName = "/dev/ttyACM0"; // example Linux portname | ||
//String portName = "COM1"; // example windows portname | ||
//String portName = "/dev/tty.usbserial-XXX"; | ||
|
||
|
||
|
||
long lastDataTime = millis(); | ||
boolean connected = false; | ||
|
||
void setup() { | ||
|
||
size (1600, 800, P3D); | ||
arduino = new Serial(this, portName, 1000000); | ||
} | ||
|
||
void draw() { | ||
|
||
if (millis() - lastDataTime > 1000 && connected == true) { | ||
// we were connected, but have received no data for 1s. Lets reconnect | ||
connected = false; | ||
arduino.stop(); | ||
// best to wait for serial port to free up | ||
delay(250); | ||
try{ | ||
arduino = new Serial(this, portName, 1000000); | ||
} catch (RuntimeException ex) { | ||
// todo: look for better way to handle errors. the following is equivalent to 'retry'. | ||
connected = true; | ||
println(ex); | ||
} | ||
} | ||
textSize(22); | ||
translate(width/2, height/2, 0); | ||
if (connected) { | ||
background(0,150,0); // gray | ||
text("Connected to: " + portName, -300, -300); | ||
} else { | ||
background(150,0,0); // red | ||
text("Not connected to: " + portName + ", check portName/portIndex", -300, -300); | ||
} | ||
|
||
drawBox("gyro (raw)\n","✓ has yaw\n× major drift", -450, gyroPitch, gyroRoll, gyroYaw); | ||
drawBox("gyro (corrected)\n","✓ has yaw\n× minor drift", -150, gyroCorrectedPitch, gyroCorrectedRoll, gyroCorrectedYaw); | ||
drawBox("accel (raw)\n","✓ zero drift\n× no yaw + noisy", 150, accPitch, accRoll, accYaw); | ||
drawBox("complementary\n","✓great pitch/roll\n× minor yaw drift", 450, complementaryPitch, complementaryRoll, complementaryYaw); | ||
|
||
} | ||
|
||
/* This draws a moving 3d box representing roll/pitch/yaw including textual stats */ | ||
void drawBox(String name, String description, int xShift, float pitch, float roll, float yaw) { | ||
pushMatrix(); | ||
// Rotate the object | ||
translate(xShift,0,0); | ||
rotateX(radians(-pitch)); | ||
rotateZ(radians(-roll)); | ||
rotateY(radians(yaw)); | ||
|
||
textSize(16); | ||
|
||
fill(0, 76, 183); | ||
box (160, 40, 300); // Draw box | ||
fill(255, 255, 255); | ||
text(name, -60, 5, 151); | ||
popMatrix(); | ||
text( name | ||
+ description | ||
+ "\npitch: " + int(pitch) | ||
+ "\nroll: " + int(roll) | ||
+ "\nyaw: " + int(yaw) | ||
, xShift -20, 200); | ||
|
||
} | ||
|
||
|
||
void serialEvent (Serial myPort) { | ||
|
||
String data = myPort.readStringUntil('\n'); | ||
// if you got any bytes other than the linefeed: | ||
if (data != null) { | ||
connected = true; | ||
lastDataTime = millis(); | ||
data = trim(data); | ||
|
||
String items[] = split(data, ','); | ||
if (items.length > 1) { | ||
//--- Roll,Pitch in degrees | ||
gyroRoll = float(items[0]); | ||
gyroPitch = float(items[1]); | ||
gyroYaw = float(items[2]); | ||
gyroCorrectedRoll = float(items[3]); | ||
gyroCorrectedPitch = float(items[4]); | ||
gyroCorrectedYaw = float(items[5]); | ||
accRoll = float(items[6]); | ||
accPitch = float(items[7]); | ||
accYaw = float(items[8]); | ||
complementaryRoll = float(items[9]); | ||
complementaryPitch = float(items[10]); | ||
complementaryYaw = float(items[11]); | ||
} | ||
} | ||
} |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is an integer division, but looking at the result, this should rather be a float division. If
lastFrequency
is0
, becauselastInterval
is too large, you getINFINTIY
values in your later calculations.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've changed it to:
Given up on this PR being merged tbh (It's a year old) - and the build failure below is the cherry on the top. It's trying to compile it against an UNO by the looks of it. :(
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah I totally understand that. I was just stumbling over it and used your code and found the fix. Leaving it here for others may try to use it. Thanks for your work!