1. Summary
  2. Files
  3. Support
  4. Report Spam
  5. Create account
  6. Log in

EV3 C-code for third party devices (I2C)

Discussion specific to NXT-G, NXC, NBC, RobotC, Lejos, and more.

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

Postby doc-helmut » 09 Nov 2013, 12:42

no idea anybody why this effing btn press does not exit the program properly?
regards,
HaWe
±≠≈αγδεωΔΦΣ∫√∅∞
NXC CHESS for NXT: http://www.mindstormsforum.de/viewtopic.php?f=70&t=6790
indispensable for NXC + EV3-C: easy + trouble-free network & sensor+motor remote control for rs485, BT, USB!
User avatar
doc-helmut
 
Posts: 2424
Joined: 29 Sep 2010, 14:25

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

Postby totokan » 09 Nov 2013, 14:32

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.
totokan
 
Posts: 45
Joined: 28 Sep 2013, 04:22

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

Postby doc-helmut » 09 Nov 2013, 15:22

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?
Last edited by doc-helmut on 09 Nov 2013, 15:28, edited 2 times in total.
regards,
HaWe
±≠≈αγδεωΔΦΣ∫√∅∞
NXC CHESS for NXT: http://www.mindstormsforum.de/viewtopic.php?f=70&t=6790
indispensable for NXC + EV3-C: easy + trouble-free network & sensor+motor remote control for rs485, BT, USB!
User avatar
doc-helmut
 
Posts: 2424
Joined: 29 Sep 2010, 14:25

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

Postby totokan » 09 Nov 2013, 15:25

Does it exit if you are continually holding down the button?
totokan
 
Posts: 45
Joined: 28 Sep 2013, 04:22

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

Postby doc-helmut » 09 Nov 2013, 15:39

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;
}
regards,
HaWe
±≠≈αγδεωΔΦΣ∫√∅∞
NXC CHESS for NXT: http://www.mindstormsforum.de/viewtopic.php?f=70&t=6790
indispensable for NXC + EV3-C: easy + trouble-free network & sensor+motor remote control for rs485, BT, USB!
User avatar
doc-helmut
 
Posts: 2424
Joined: 29 Sep 2010, 14:25

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

Postby gloomyandy » 09 Nov 2013, 16:05

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...
User avatar
gloomyandy
 
Posts: 320
Joined: 29 Sep 2010, 05:03

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

Postby doc-helmut » 09 Nov 2013, 16:12

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/mindboards/viewtopic.php?f=3&t=1977&start=10#p17585

About the make file thing: yes, sure, strangely, but why?
regards,
HaWe
±≠≈αγδεωΔΦΣ∫√∅∞
NXC CHESS for NXT: http://www.mindstormsforum.de/viewtopic.php?f=70&t=6790
indispensable for NXC + EV3-C: easy + trouble-free network & sensor+motor remote control for rs485, BT, USB!
User avatar
doc-helmut
 
Posts: 2424
Joined: 29 Sep 2010, 14:25

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

Postby doc-helmut » 09 Nov 2013, 16:55

now not at all Lauros code can be compiled - same error!

what the fu** ...
regards,
HaWe
±≠≈αγδεωΔΦΣ∫√∅∞
NXC CHESS for NXT: http://www.mindstormsforum.de/viewtopic.php?f=70&t=6790
indispensable for NXC + EV3-C: easy + trouble-free network & sensor+motor remote control for rs485, BT, USB!
User avatar
doc-helmut
 
Posts: 2424
Joined: 29 Sep 2010, 14:25

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

Postby doc-helmut » 09 Nov 2013, 17:59

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).
regards,
HaWe
±≠≈αγδεωΔΦΣ∫√∅∞
NXC CHESS for NXT: http://www.mindstormsforum.de/viewtopic.php?f=70&t=6790
indispensable for NXC + EV3-C: easy + trouble-free network & sensor+motor remote control for rs485, BT, USB!
User avatar
doc-helmut
 
Posts: 2424
Joined: 29 Sep 2010, 14:25

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

Postby lvoc » 11 Nov 2013, 02:07

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;
}

Lauro
http://www.robotnav.com
lvoc
 
Posts: 38
Joined: 10 Sep 2013, 13:34

PreviousNext

Return to Mindstorms Software

Who is online

Users browsing this forum: No registered users and 0 guests

cron