Page 3 of 6

Re: EV3 C-code for third party devices (I2C)

Posted: 09 Nov 2013, 12:42
by HaWe
no idea anybody why this effing btn press does not exit the program properly?

Re: EV3 C-code for third party devices (I2C)

Posted: 09 Nov 2013, 14:32
by totokan

Code: Select all

    sleep(1);
    if ( checkButtons() )  break;
There's your problem. What does sleep(1) do? How often will your if statement be evaluated?
Furthermore, in a traditional embedded system, you would want a button press to trigger an interrupt, but here we should just make sure the button press is getting checked in every part of the program. Make sure you check the button press in every loop, not just the main one, and make sure it causes functions to return a value (traditionally -1) that indicates to the caller that a button was pressed and it should exit.

Re: EV3 C-code for third party devices (I2C)

Posted: 09 Nov 2013, 15:22
by HaWe
I don't understand where you observe the problem.

Code: Select all

while(1)   {
    get_xg1300l_gyro(&angle, &rate, &acc_x, &acc_y, &acc_z);

    sprintf(buf,"Angle = %0.2f [deg]", angle);
    LcdText(1, 0, 10, buf);
    sprintf(buf,"Rate = %0.2f [deg/sec]", rate);
    LcdText(1, 0, 30, buf);
    //... SNIP
     
    sleep(1);
    if ( checkButtons() )  break;
  }

all the code is inside of a perpetual while loop.

sleep(1) waits 1ms before checking the buttons (CMIIW)

The buttons are then checked if pressed or not.
checkButtons returns (0) if no button is pressed and any positve value if one has been pressed.

So if no button is pressed the while loop continues (what it actually does)
and otherwise the while loop exits (what it actually does, too).

After it exits the loop, the program (sensor polling) stops (what it actually does))
and all moduls and devices are closed (what actually happens in some degree- but not correctly, apperently).

Code: Select all

close_xg1300l_gyro();

  OutputClose();
  OutputExit();
  ButtonLedClose();
  ButtonLedExit();
  LcdExit();
 
  return 1;
Where exactly is the mistake?

Re: EV3 C-code for third party devices (I2C)

Posted: 09 Nov 2013, 15:25
by totokan
Does it exit if you are continually holding down the button?

Re: EV3 C-code for third party devices (I2C)

Posted: 09 Nov 2013, 15:39
by HaWe
it is supposed to exit because it doesn't wait for btn-up.

strangely, I can't compile the code any longer, there suddenly is an error I didn't observe before:

Code: Select all

make: *** No rule to make target `lms2012.o', needed by `all'.  Stop.
here is the complete code:

Code: Select all

#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/ioctl.h>

#include "lms2012.h"
#include "ev3_lcd.h"

#include <pthread.h>

#include "ev3_constants.h"
#include "ev3_command.h"
#include "ev3_button.h"
#include "ev3_timer.h"
#include "ev3_sound.h"
#include "ev3_output.h"


//Runtime constants
const int MAX_SAMPLES = 1000;

//Global variables and constants used by the sensor handling functions

const int XGL_PACKET_SIZE = 10; //2(gyyro angle) + 2(gyro rate) + 2(acc x) + 2(acc y) + 2(acc z)
const char XGL_PORT = 0x0; //The ports are designated as XGL_PORT_NUMBER-1
int xgl_device_file;

IIC *pXgl;

int init_xg1300l_gyro()
{
    IICDAT IicDat;
    char buf[120];

    //Open the device xgl_device_file
    if((xgl_device_file = open(IIC_DEVICE_NAME, O_RDWR | O_SYNC)) == -1)   {
      sprintf(buf, "Failed to open device");
      LcdText(1, 0, 110, buf);
      return 0;
    }

    pXgl = (IIC*)mmap(0, sizeof(IIC), PROT_READ | PROT_WRITE, MAP_FILE | MAP_SHARED, xgl_device_file, 0);

    if (pXgl == MAP_FAILED)  {
      sprintf(buf, "Map failed");
      LcdText(1, 0, 110, buf);
      return 0;
    }

    //Setup IIC to read 2 packets
    IicDat.Port = XGL_PORT;
    IicDat.Time = 0;
    IicDat.Repeat = 0;
    IicDat.RdLng = XGL_PACKET_SIZE;
    IicDat.WrLng = 2;

    // Set the device I2C address
    IicDat.WrData[0] = 0x01;

    // Specify the register that will be read (0x42 = angle)
    IicDat.WrData[1] = 0x42;

    // Setup I2C comunication
    ioctl(xgl_device_file,IIC_SETUP,&IicDat);
    sprintf(buf,"Device is ready");
    LcdText(1, 0, 110, buf);

    return 1;
}

void get_xg1300l_gyro(float *angle, float *rate, float *acc_x, float *acc_y, float *acc_z)
{
    //Compute angle, angular rate and accelerations

    *acc_z = (pXgl->Raw[XGL_PORT][pXgl->Actual[XGL_PORT]][0]*256+pXgl->Raw[XGL_PORT][pXgl->Actual[XGL_PORT]][1])/100.0;
    *acc_y = (pXgl->Raw[XGL_PORT][pXgl->Actual[XGL_PORT]][2]*256+pXgl->Raw[XGL_PORT][pXgl->Actual[XGL_PORT]][3])/100.0;
    *acc_x = (pXgl->Raw[XGL_PORT][pXgl->Actual[XGL_PORT]][4]*256+pXgl->Raw[XGL_PORT][pXgl->Actual[XGL_PORT]][5])/100.0;
    *rate  = (pXgl->Raw[XGL_PORT][pXgl->Actual[XGL_PORT]][6]*256+pXgl->Raw[XGL_PORT][pXgl->Actual[XGL_PORT]][7])/100.0;
    *angle = (pXgl->Raw[XGL_PORT][pXgl->Actual[XGL_PORT]][8]*256+pXgl->Raw[XGL_PORT][pXgl->Actual[XGL_PORT]][9])/100.0;
}

void close_xg1300l_gyro()     //Close the device xgl_device_file
{
    char buf[120];

    sprintf(buf,"Closing device\n");
    LcdText(1, 0, 110, buf);

    close(xgl_device_file);
}

int main()
{
  int   i;
  char  buf[120];

  float angle;
  float rate;
  float acc_x;
  float acc_y;
  float acc_z;

  LcdInit();
  LcdClean();
  OutputInit();
  ButtonLedInit();

  if(!init_xg1300l_gyro())
      return -1;

  LcdClean();

  while(1)   {
    get_xg1300l_gyro(&angle, &rate, &acc_x, &acc_y, &acc_z);

    sprintf(buf,"Angle = %0.2f [deg]", angle);
    LcdText(1, 0, 10, buf);
    sprintf(buf,"Rate = %0.2f [deg/sec]", rate);
    LcdText(1, 0, 30, buf);
    sprintf(buf,"AccX = %0.2f [g]", acc_x);
    LcdText(1, 0, 50, buf);
    sprintf(buf,"AccY = %0.2f [g]", acc_y);
    LcdText(1, 0, 70, buf);
    sprintf(buf,"AccZ = %0.2f [g]", acc_z);
    LcdText(1, 0, 90, buf);

    sleep(1);
    if ( checkButtons() )  break;
  }

  close_xg1300l_gyro();

  OutputClose();
  OutputExit();
  ButtonLedClose();
  ButtonLedExit();
  LcdExit();

  return 1;
}

Re: EV3 C-code for third party devices (I2C)

Posted: 09 Nov 2013, 16:05
by gloomyandy
Doc if that is a standard posix c library sleep call (i.e. it has not been redefined by some sort of macro), then it will be sleeping for 1 second not 1mS:
http://linux.die.net/man/3/sleep
you may want to use nanosleep or usleep instead.

As to your error, that seems to be some sort of makefile issue...

Re: EV3 C-code for third party devices (I2C)

Posted: 09 Nov 2013, 16:12
by HaWe
I actually doubt that it's 1sec wait because the values have been changing insanely quick before (see Lauro's original code).
https://sourceforge.net/apps/phpbb/mind ... =10#p17585

About the make file thing: yes, sure, strangely, but why?

Re: EV3 C-code for third party devices (I2C)

Posted: 09 Nov 2013, 16:55
by HaWe
now not at all Lauros code can be compiled - same error!

what the fu** ...

Re: EV3 C-code for third party devices (I2C)

Posted: 09 Nov 2013, 17:59
by HaWe
Slowly I come to the conclusion that this C thing is such a mess that I guess I will finally have to abandon it.
I woud give any non-professional the advice to never try it ever (actually besides myself no one of the > 3500 members of our German forum already tried it ever - or dropped it in case he did, surely because of the same reasons).

Re: EV3 C-code for third party devices (I2C)

Posted: 11 Nov 2013, 02:07
by lvoc
I observed similar issues as the ones you described. However, since I was successful running the button test program, I trued using ButtonWaitForAnyPress (used in the button test program) instead of checkButtons. This time the program worked as expected. The "sleep" function was there in the initial program to introduce one second delays between readings. You could comment it out if you need more frequent readings, alternatively you can use usleep (micro second sleep) to specify delays shorter than one second.

Regarding your concerns about John's functions not being compatible with the Lego “lms2012.h” include file. That should not be a problem, It is always possible to redefine some constants as needed (similar to what I did). That solution is even available with commercial (closed source) libraries.

Here is the code I tested:

Code: Select all

#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/ioctl.h>

#include "lms2012.h"
#include "ev3_button.h"
#include "ev3_lcd.h"
   
//Runtime constants
const int MAX_SAMPLES = 1000;

//Global variables and constants used by the sensor handling functions

#define TITLE_DELAY 1000
const int XGL_PACKET_SIZE = 10; //2(gyyro angle) + 2(gyro rate) + 2(acc x) + 2(acc y) + 2(acc z)
const char XGL_PORT = 0x0; //The ports are designated as XGL_PORT_NUMBER-1
int xgl_device_file;

IIC *pXgl;

int init_xg1300l_gyro()
{
    IICDAT IicDat;
    char buf[120];

    //Open the device xgl_device_file
    if((xgl_device_file = open(IIC_DEVICE_NAME, O_RDWR | O_SYNC)) == -1)   {
      sprintf(buf, "Failed to open device");
      LcdText(1, 0, 60, buf);
      return 0;
    }

    pXgl = (IIC*)mmap(0, sizeof(IIC), PROT_READ | PROT_WRITE, MAP_FILE | MAP_SHARED, xgl_device_file, 0);

    if (pXgl == MAP_FAILED)  {
      sprintf(buf, "Map failed");
      LcdText(1, 0, 60, buf);
      return 0;
    }
   
    //Setup IIC to read 2 packets
    IicDat.Port = XGL_PORT;
    IicDat.Time = 0;
    IicDat.Repeat = 0;
    IicDat.RdLng = XGL_PACKET_SIZE;
    IicDat.WrLng = 2;
   
    // Set the device I2C address
    IicDat.WrData[0] = 0x01;
   
    // Specify the register that will be read (0x42 = angle)
    IicDat.WrData[1] = 0x42;
   
    // Setup I2C comunication
    ioctl(xgl_device_file,IIC_SETUP,&IicDat);
    sprintf(buf,"Device is ready");
    LcdText(1, 0, 60, buf);
   
    return 1;
}

void get_xg1300l_gyro(float *angle, float *rate, float *acc_x, float *acc_y, float *acc_z)
{
    //Compute angle, angular rate and accelerations
   
    *acc_z = (pXgl->Raw[XGL_PORT][pXgl->Actual[XGL_PORT]][0]*256+pXgl->Raw[XGL_PORT][pXgl->Actual[XGL_PORT]][1])/100.0;
    *acc_y = (pXgl->Raw[XGL_PORT][pXgl->Actual[XGL_PORT]][2]*256+pXgl->Raw[XGL_PORT][pXgl->Actual[XGL_PORT]][3])/100.0;
    *acc_x = (pXgl->Raw[XGL_PORT][pXgl->Actual[XGL_PORT]][4]*256+pXgl->Raw[XGL_PORT][pXgl->Actual[XGL_PORT]][5])/100.0;
    *rate  = (pXgl->Raw[XGL_PORT][pXgl->Actual[XGL_PORT]][6]*256+pXgl->Raw[XGL_PORT][pXgl->Actual[XGL_PORT]][7])/100.0;
    *angle = (pXgl->Raw[XGL_PORT][pXgl->Actual[XGL_PORT]][8]*256+pXgl->Raw[XGL_PORT][pXgl->Actual[XGL_PORT]][9])/100.0;
}

void close_xg1300l_gyro()     //Close the device xgl_device_file
{
	char buf[120];

	sprintf(buf,"Closing device\n");
	LcdText(1, 0, 60, buf);

	close(xgl_device_file);
}

int main()
{
  char  buf[120];

  float angle;
  float rate;
  float acc_x;
  float acc_y;
  float acc_z; 
   
  ButtonLedInit();
  LcdInit();
  LcdClean();

  if(!init_xg1300l_gyro())
      return -1;

  LcdClean();

  while(1)
	{
    get_xg1300l_gyro(&angle, &rate, &acc_x, &acc_y, &acc_z);
   
    sprintf(buf,"Angle = %0.2f [deg]", angle);
    LcdText(1, 0, 10, buf);
    sprintf(buf,"Rate = %0.2f [deg/sec]", rate);
    LcdText(1, 0, 30, buf);
    sprintf(buf,"AccX = %0.2f [g]", acc_x);
    LcdText(1, 0, 50, buf);
    sprintf(buf,"AccY = %0.2f [g]", acc_y);
    LcdText(1, 0, 70, buf);
    sprintf(buf,"AccZ = %0.2f [g]", acc_z);
    LcdText(1, 0, 90, buf);
  	if(ButtonWaitForAnyPress(TITLE_DELAY) == BUTTON_ID_ESCAPE)
			break;
    sleep(1);
  }

  close_xg1300l_gyro();
  LcdExit();
  ButtonLedExit();
  return 1;
}