Home › Forums › Forums › Technical Support for BerryIMU › [Resolved]Unable to open I2C bus
- This topic has 35 replies, 3 voices, and was last updated 8 years, 6 months ago by jawood.
- AuthorPosts
- May 14, 2015 at 1:50 am #3980jawoodParticipant
yeah tried that no change same error
May 14, 2015 at 8:19 am #3982Mark WilliamsKeymasterMay 14, 2015 at 8:42 am #3983jawoodParticipantsudo apt-get install libi2c-dev
Reading package lists… Done
Building dependency tree
Reading state information… Done
libi2c-dev is already the newest version.
0 upgraded, 0 newly installed, 0 to remove and 4 not upgraded.May 14, 2015 at 8:58 am #3985Mark WilliamsKeymasterWhen you copy the text of the web page.. some of the commands are converted.
I changed how the text is shown in the web page.Refresh the instructions and hey copy the compile statement again.
Or, view the README in the folder for the correct compile statement
Mark --OzzMaker.com --
May 14, 2015 at 9:26 am #3986jawoodParticipantgcc -o gyro_accelerometer_tutorial02 -lm gyro_accelerometer_tutorial02.c
sdl-config --cflags
sdl-config --libs
-lSDL_image -lSDL_gfx
gyro_accelerometer_tutorial02.c: In function ‘startSDL’:
gyro_accelerometer_tutorial02.c:217:19: warning: assignment discards ‘const’ qualifier from pointer target type [enabled by default]
gyro_accelerometer_tutorial02.c: In function ‘graphics’:
gyro_accelerometer_tutorial02.c:280:38: warning: assignment makes pointer from integer without a cast [enabled by default]
gyro_accelerometer_tutorial02.c:281:39: warning: assignment makes pointer from integer without a cast [enabled by default]sudo ./gyro_accelerometer_tutorial02 It Works!!!! So cool!!!!
Want to use this as a leveller for my Caravan connected to 4 worm shafts to auto level the Van. (I think the update rate is going to be to slow thou.)
Thou it is working now it is quite slow to update and appears to be slightly out of calibration when on a flat level surface after a second or so when it stabilize I have to hold the unit at about 10 degrees off flat on the left/right axis to show flat on the PiScreen, front to back seems to be ok.
May 14, 2015 at 9:28 am #3987jawoodParticipantOw one other thing I would love to be able to run it as a full screen app, so you cant see the task bar or anything else. Would appreciate some advise on how to do that!
And thanks for all your help getting it going!
May 14, 2015 at 9:56 am #3988Mark WilliamsKeymasterplay around with the complimentary filter constant
#define AA 0.97 // complementary filter constant
This controls how much of the gyro or the accelerometer is used in the fused angle.
lowering the value will result in a faster correct angle result.Regarding speed;
If you are using a PiScreen to display this output, try increasing the speed the PiScreen by changing the speed value in /boot/config.txtdtoverlay=piscreen,speed=16000000,rotate=90
try 32000000.. if the colors dont look right, try 24000000. You will have to reboot to for the change to take effect.
You can also try lowering the delay in the loop;
#define DT 0.2 //
loop period. 0.2 = 200ms
It is currently set to 200ms… remember that you need to keep a constant loop time, otherwise your gyro angle will drift too much. The loop time is the first value printed out to the console.Mark --OzzMaker.com --
May 14, 2015 at 10:16 am #3989jawoodParticipantthanks for the sugestions I was wondering if adding the kalman filter would make it a bit better. I had a look and it seems pretty straight forward to add it.
I think change this graphics(CFangleX,CFangleY); to graphics(kalmanX,kalmanY); and add the functions variables etc..
May 14, 2015 at 10:55 am #3991jawoodParticipantI think this should do it. Whats in bold I added.
/*
This program is used to create an Inclinometer using a
Raspberry Pi and an IMUhttps://ozzmaker.com/2014/12/12/inclinometer-using-raspberry-pi-imu/
Copyright (C) 2014 Mark Williams
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place – Suite 330, Boston,
MA 02111-1307, USA
*/#include “SDL.h”
#include “SDL/SDL_image.h”
#include <unistd.h>
#include <math.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
#include <time.h>
#include “sensor.c”#define DT 0.2 //
loop period. 0.2 = 200ms
#define AA 0.97 // complementary filter constant#define A_GAIN 0.0573 // [deg/LSB]
#define G_GAIN 0.070 // [deg/s/LSB]
#define RAD_TO_DEG 57.29578
#define M_PI 3.14159265358979323846//Used by Kalman Filters
float Q_angle = 0.01;
float Q_gyro = 0.0003;
float R_angle = 0.01;
float x_bias = 0;
float y_bias = 0;
float XP_00 = 0, XP_01 = 0, XP_10 = 0, XP_11 = 0;
float YP_00 = 0, YP_01 = 0, YP_10 = 0, YP_11 = 0;
float KFangleX = 0.0;
float KFangleY = 0.0;float kalmanFilterX(float accAngle, float gyroRate);
float kalmanFilterY(float accAngle, float gyroRate);
int graphics(float carRoll, float carPitch);
int startSDL();
SDL_Surface* screen = NULL;
SDL_Surface* inclinometerJeepFront = NULL;
SDL_Surface* inclinometerJeepSide = NULL;
SDL_Surface* inclinometerOverlay = NULL;
SDL_Surface* compatibleInclinometerJeepFront = NULL;
SDL_Surface* compatibleInclinometerJeepSide = NULL;
SDL_Surface* compatibleInclinometerOverlay = NULL;
SDL_Surface* rotationInclinometerJeepFront = NULL;
SDL_Surface* rotationInclinometerJeepSide = NULL;
SDL_Rect inclinometerJeepOverlayPosition;
SDL_Rect inclinometerJeepFrontPosition;
SDL_Rect inclinometerJeepSidePosition;SDL_VideoInfo* videoInfo;
void INThandler(int sig)
{
SDL_FreeSurface(screen);
SDL_Quit();
signal(sig, SIG_IGN);
exit(0);
}int mymillis()
{
struct timeval tv;
gettimeofday(&tv, NULL);
return (tv.tv_sec) * 1000 + (tv.tv_usec)/1000;
}int timeval_subtract(struct timeval *result, struct timeval *t2, struct timeval *t1)
{
long int diff = (t2->tv_usec + 1000000 * t2->tv_sec) – (t1->tv_usec + 1000000 * t1->tv_sec);
result->tv_sec = diff / 1000000;
result->tv_usec = diff % 1000000;
return (diff<0);
}int main(int argc, char *argv[])
{float rate_gyr_y = 0.0; // [deg/s]
float rate_gyr_x = 0.0; // [deg/s]
float rate_gyr_z = 0.0; // [deg/s]int acc_raw[3];
int mag_raw[3];
int gyr_raw[3];float gyroXangle = 0.0;
float gyroYangle = 0.0;
float gyroZangle = 0.0;
float AccYangle = 0.0;
float AccXangle = 0.0;
float CFangleX = 0.0;
float CFangleY = 0.0;int startInt = mymillis();
struct timeval tvBegin, tvEnd,tvDiff;signed int acc_y = 0;
signed int acc_x = 0;
signed int acc_z = 0;
signed int gyr_x = 0;
signed int gyr_y = 0;
signed int gyr_z = 0;signal(SIGINT, INThandler);
enableIMU();
gettimeofday(&tvBegin, NULL);
if(argc <=1)
startSDL();
else if (strcmp(argv[1],”nosdl”)!= 0)
startSDL();while(1)
{
startInt = mymillis();//read ACC and GYR data
readACC(acc_raw);
readGYR(gyr_raw);//Convert Gyro raw to degrees per second
rate_gyr_x = (float) gyr_raw[0] * G_GAIN;
rate_gyr_y = (float) gyr_raw[1] * G_GAIN;
rate_gyr_z = (float) gyr_raw[2] * G_GAIN;//Calculate the angles from the gyro
gyroXangle+=rate_gyr_x*DT;
gyroYangle+=rate_gyr_y*DT;
gyroZangle+=rate_gyr_z*DT;//Convert Accelerometer values to degrees
AccXangle = (float) (atan2(acc_raw[1],acc_raw[2])+M_PI)*RAD_TO_DEG;
AccYangle = (float) (atan2(acc_raw[2],acc_raw[0])+M_PI)*RAD_TO_DEG;//Change the rotation value of the accelerometer to -/+ 180 and move the Y axis ‘0’ point to up.
//Two different pieces of code are used depending on how your IMU is mounted.
//If IMU is upside down
/*
if (AccXangle >180)
AccXangle -= (float)360.0;AccYangle-=90;
if (AccYangle >180)
AccYangle -= (float)360.0;
*///If IMU is up the correct way, use these lines
AccXangle -= (float)180.0;
if (AccYangle > 90)
AccYangle -= (float)270;
else
AccYangle += (float)90;//Kalman Filter
float kalmanX = kalmanFilterX(AccXangle, rate_gyr_x);
float kalmanY = kalmanFilterY(AccYangle, rate_gyr_y);
printf (“33[22;31mkalmanX %7.3f 33[22;36mkalmanY %7.3f\t\e[m”,kalmanX,kalmanY);//Complementary filter used to combine the accelerometer and gyro values.
CFangleX=AA*(CFangleX+rate_gyr_x*DT) +(1 – AA) * AccXangle;
CFangleY=AA*(CFangleY+rate_gyr_y*DT) +(1 – AA) * AccYangle;printf (” GyroX %7.3f \t AccXangle \e[m %7.3f \t 33[22;31mCFangleX %7.3f33[0m\t GyroY %7.3f \t AccYangle %7.3f \t 33[22;36mCFangleY %7.3f\t33[0m\n”,gyroXangle,AccXangle,CFangleX,gyroYangle,AccYangle,CFangleY);
if(argc <=1)
graphics(kalmanX,kalmanY);
else if (strcmp(argv[1],”nosdl”)!= 0)
graphics(kalmanX,kalmanY);//Each loop should be at least 20ms.
while(mymillis() – startInt < (DT*1000))
{
usleep(100);
}printf(“Loop Time %d\t”, mymillis()- startInt);
}
}int startSDL()
{
//fb1 = small TFT. fb0 = HDMI/RCA output
putenv(“SDL_FBDEV=/dev/fb0”);//Initialize SDL and disable mouse
SDL_Init(SDL_INIT_VIDEO);
SDL_ShowCursor(SDL_DISABLE);//Get information about the current video device. E.g. resolution and bits per pixal
videoInfo = SDL_GetVideoInfo ();//Setup a Video mode.
screen = SDL_SetVideoMode(videoInfo->current_w, videoInfo->current_h, videoInfo->vfmt->BitsPerPixel, SDL_SWSURFACE );
if ( screen == NULL ) {
fprintf(stderr, “Unable to setvideo: %s\n”, SDL_GetError());
exit(1);
}//Load image.
inclinometerJeepFront = IMG_Load(“inclinometerJeepFront.png”);
if (inclinometerJeepFront == NULL){
printf(“error loading JeepFront image\n”);
SDL_Quit();
exit(1);
}
//Convert the image to a format we can use.
compatibleInclinometerJeepFront = SDL_DisplayFormatAlpha(inclinometerJeepFront);//Load image.
inclinometerJeepSide = IMG_Load(“inclinometerJeepSide.png”);
if (inclinometerJeepSide == NULL){
printf(“error loading JeepSide image\n”);
SDL_Quit();
exit(1);
}
//Convert the image to a format we can use.
compatibleInclinometerJeepSide = SDL_DisplayFormatAlpha(inclinometerJeepSide);//Load image.
inclinometerOverlay = IMG_Load(“inclinometerOverlay.png”);
if (inclinometerOverlay == NULL){
printf(“error loading Overlay image\n”);
SDL_Quit();
exit(1);
}
//Convert the image to a format we can use.
compatibleInclinometerOverlay = SDL_DisplayFormatAlpha(inclinometerOverlay);//Position the overlay in the middle of the screen. screen heigth minus the height of the overlay image.
inclinometerJeepOverlayPosition.y = (videoInfo->current_h/2)-(compatibleInclinometerOverlay->h/2);}
int graphics(float carRoll, float carPitch)
{//Set all pixals to black to clear the last image.
SDL_FillRect(screen,NULL,0x000000);//Position of both jeep images.
inclinometerJeepFrontPosition.x = 30;
inclinometerJeepFrontPosition.y = (videoInfo->current_h/2)-(compatibleInclinometerJeepFront->h/2);
inclinometerJeepSidePosition.x = 262;
inclinometerJeepSidePosition.y = (videoInfo->current_h/2)-(compatibleInclinometerJeepFront->h/2);//Rotate the images based on pitch and roll.
rotationInclinometerJeepSide = rotozoomSurface(compatibleInclinometerJeepSide, carPitch, 1.0, 0.0);
rotationInclinometerJeepFront = rotozoomSurface(compatibleInclinometerJeepFront, carRoll, 1.0, 0.0);//Recenter pivot point.
inclinometerJeepFrontPosition.x -= rotationInclinometerJeepFront->w/2-compatibleInclinometerJeepFront->w/2;
inclinometerJeepFrontPosition.y -= rotationInclinometerJeepFront->h/2-compatibleInclinometerJeepFront->h/2;
inclinometerJeepSidePosition.x -= rotationInclinometerJeepSide->w/2-compatibleInclinometerJeepSide->w/2;
inclinometerJeepSidePosition.y -= rotationInclinometerJeepSide->h/2-compatibleInclinometerJeepSide->h/2;//Blit the three iamges to the surface.
SDL_BlitSurface( compatibleInclinometerOverlay, NULL, screen, &inclinometerJeepOverlayPosition);
SDL_BlitSurface( rotationInclinometerJeepFront, NULL, screen, &inclinometerJeepFrontPosition);
SDL_BlitSurface( rotationInclinometerJeepSide, NULL, screen, &inclinometerJeepSidePosition);//Send the surface to the display.
SDL_Flip(screen);//Free surfaces.
SDL_FreeSurface(screen);
SDL_FreeSurface(rotationInclinometerJeepFront);
SDL_FreeSurface(rotationInclinometerJeepSide);
return 0;}
float kalmanFilterX(float accAngle, float gyroRate)
{
float y, S;
float K_0, K_1;KFangleX += DT * (gyroRate – x_bias);
XP_00 += – DT * (XP_10 + XP_01) + Q_angle * DT;
XP_01 += – DT * XP_11;
XP_10 += – DT * XP_11;
XP_11 += + Q_gyro * DT;y = accAngle – KFangleX;
S = XP_00 + R_angle;
K_0 = XP_00 / S;
K_1 = XP_10 / S;KFangleX += K_0 * y;
x_bias += K_1 * y;
XP_00 -= K_0 * XP_00;
XP_01 -= K_0 * XP_01;
XP_10 -= K_1 * XP_00;
XP_11 -= K_1 * XP_01;return KFangleX;
}float kalmanFilterY(float accAngle, float gyroRate)
{
float y, S;
float K_0, K_1;KFangleY += DT * (gyroRate – y_bias);
YP_00 += – DT * (YP_10 + YP_01) + Q_angle * DT;
YP_01 += – DT * YP_11;
YP_10 += – DT * YP_11;
YP_11 += + Q_gyro * DT;y = accAngle – KFangleY;
S = YP_00 + R_angle;
K_0 = YP_00 / S;
K_1 = YP_10 / S;KFangleY += K_0 * y;
y_bias += K_1 * y;
YP_00 -= K_0 * YP_00;
YP_01 -= K_0 * YP_01;
YP_10 -= K_1 * YP_00;
YP_11 -= K_1 * YP_01;return KFangleY;
}May 14, 2015 at 11:08 am #3992jawoodParticipantOw yeah that’s better very stable now and accurate. Cant believe the difference just using the kalman filter makes.
Now all I need to know is how to make it run as a full screen app without taskbar
May 14, 2015 at 11:10 am #3994Mark WilliamsKeymasteryou are right… in theory, it shouldn’t be too hard. The code looks correct
Mark --OzzMaker.com --
May 14, 2015 at 11:39 am #3995jawoodParticipantYeah it works great now with the Kalman Filter applied.
I would like to be able to get it to run without the blue bar at the top of the window and how to get it to open full screen. Any help with that would be much appreciated. ThanksMay 14, 2015 at 11:58 am #3996jawoodParticipantOw one more thing I just did the screen blanking thing and its still blanking.
sudo apt-get install x11-xserver-utils
sudo nano /etc/xdg/lxsession/LXDE/autostartadded
@xset s off # don’t activate screensaver
@xset -dpms # disable DPMS (Energy Star) features.
@xset s noblank # don’t blank the video deviceReboot. Screen still blanking after 10mins
May 14, 2015 at 12:20 pm #3997jawoodParticipantIm assuming I add
SDL_WM_ToggleFullScreen(SDL_Surface *surface);
I added it to function:-
//Initialise SDL and Disable Mouse
SDL_Init(SDL_INIT_VIDEO);
SDL_ShowCursor(SDL_DIABLE);
SDL_WM_ToggleFullScreen(SDL_Surface *surface);Compile:-
gcc -o KalmanFilterLevelMeter1 -lm LevelMeterKalmanFiltered.c
sdl-config --cflags
sdl-config --libs
-lSDL_image -lSDL_gfxAnd get error:-
LevelMeterKalmanFiltered.c: In function ‘startSDL’:
LevelMeterKalmanFiltered.c:233:26: error: expected expression before ‘SDL_Surface’
LevelMeterKalmanFiltered.c:236:19: warning: assignment discards ‘const’ qualifier from pointer target type [enabled by default]
LevelMeterKalmanFiltered.c: In function ‘graphics’:
LevelMeterKalmanFiltered.c:299:38: warning: assignment makes pointer from integer without a cast [enabled by default]
LevelMeterKalmanFiltered.c:300:39: warning: assignment makes pointer from integer without a cast [enabled by default]May 15, 2015 at 12:25 am #4001Mark WilliamsKeymasterRegarding Blanking, I needed to update that page… there has been a resent change that breaks the use of xset directly in the autostart.
The page now has;
Disable X blanking
1. Install X server utilities, they will most likely already be installed.
sudo apt-get install x11-xserver-utils
2. Create a small script which is used to change the screen saver settings.
sudo nano /etc/X11/Xsession.d/disableblank.sh
3. Add these three lines.xset s off # don't activate screensaver xset -dpms # disable DPMS (Energy Star) features. xset s noblank # don't blank the video device
4. Change the permissions on the file.
sudo chmod +x /etc/X11/Xsession.d/disableblank.sh
5. Force the file to run when X starts
sudo nano /etc/xdg/lxsession/LXDE-pi/autostart
Or /etc/xdg/lxsession/LXDE/autostart on older version of RaspbianAnd add this line to the bottom;
/etc/X11/Xsession.d/disableblank.sh
Mark --OzzMaker.com --
- AuthorPosts
- You must be logged in to reply to this topic.