Go Down

Topic: Improved Esplora TFT Horizon (Read 7161 times) previous topic - next topic

kor1989

Sep 06, 2013, 12:39 am Last Edit: Sep 06, 2013, 11:44 am by kor1989 Reason: 1
Hi, I have tried to improve the Esplora TFT Horizon making it a little more sensitive to high inclination and adding also a line to represent vertical inclination. The angles are also printed to the serial port.

Quote

/*
 Created 25 August 2013 by Corrado Possieri
*/

// first of all we need to include the libraries
#include <Esplora.h>
#include <TFT.h>            // Arduino LCD library
#include <SPI.h>

// some variables that the Esplora need to work correctly
// we have to define the center of the screen
const float X0 = EsploraTFT.width()/2.0;
const float Y0 = EsploraTFT.height()/2.0;

// and the limit values for the accelerometer
// good values not considering the acceleration impressed
// to Esplora are those (you can try also the values after comment)
int xAccMin = -180; // -150;
int xAccMax = 180; //170;
int yAccMin = -180; //-147;
int yAccMax = 180; //190;
int zAccMin = -180; //-150;
int zAccMax = 180; //170;

// we need also to save in a global variable the last angle
float lastTanAngle;
float lastZIncl;

// this function will be executed once at the beginning
void setup() {
 // we need to initialize the display
 EsploraTFT.begin();
 
 // and to select the color of the background
 EsploraTFT.background(0,0,0); // black for an higher contrast
 
 // begin the serial comunication
 Serial.begin(9600);
}

// this will run over and over
void loop() {  
 // we need to read the Accelerometer values...
 int xAxis = Esplora.readAccelerometer(X_AXIS);
 int yAxis = Esplora.readAccelerometer(Y_AXIS);
 int zAxis = Esplora.readAccelerometer(Z_AXIS);
 
 // ...and to remap them in a fixed range scale
 const int scale = 1000;
 float xIncl = map(xAxis, xAccMin, xAccMax, -scale, scale);
 float yIncl = map(yAxis, yAccMin, yAccMax, -scale, scale);
 float zIncl = map(zAxis, zAccMin, zAccMax, scale, -scale);
 
 // horizontal inclination
 float horizontalAngle = atan2(xIncl, yIncl);
 // vertical inclination
 float verticalInclination = atan2(yIncl, -zIncl);
 
 // print these values to the serial port
 Serial.print("horizontal angle: ");
 Serial.println(horizontalAngle/PI*180);
 Serial.print("verical angle: ");
 Serial.println(verticalInclination/PI*180);
 Serial.println();
 
 // no we can graph the values in the tft screen
 // this value represent the offset of the line
 // which represent the ground
 float zOffset = map(zAxis, zAccMin, zAccMax, Y0, -Y0);
 // this represent the inclination respect the horizon
 float tanAngle = xIncl/yIncl;

 // first of all we have to delete the previous lines
 // drawing black lines over them
 // horizontal inclination
 EsploraTFT.stroke(0,0,0); // we draw black over the previous lines
 EsploraTFT.line(0, -X0*lastTanAngle+Y0, 2*X0, X0*lastTanAngle+Y0);
 // vertical inclination
 EsploraTFT.line(0, -X0*lastTanAngle+lastZIncl+Y0,
   2*X0, X0*lastTanAngle+lastZIncl+Y0);

 // now we can write the new lines
 // one for horizontal inclination
 EsploraTFT.stroke(0,255,0); // this line would be green
 EsploraTFT.line(0, -X0*tanAngle+Y0, 2*X0, X0*tanAngle+Y0);
 // this line would be red
 // and one for vertical
 EsploraTFT.stroke(255,0,0);
 EsploraTFT.line(0, -X0*tanAngle+zOffset+Y0, 2*X0, X0*tanAngle+zOffset+Y0);
 
 // we will save the values for the next loop iteration
 lastTanAngle = tanAngle;
 lastZIncl = zOffset;
 
 // a little delay for stability
 delay(100);
}



I hope this will help.
Happy sketching

TheKitty



kor1989

Hi, I have tried to improve a little my code adding a Processing Sketch that permits also to understand what's going on for users which does not have the LCD

The code for Arduino has little changes that permits to send a float through serial port using an union

Quote

/*
  Created 25 August 2013 by Corrado Possieri
*/

// first of all we need to include the libraries
#include <Esplora.h>
#include <TFT.h>            // Arduino LCD library
#include <SPI.h>

// some variables that the Esplora need to work correctly
// we have to define the center of the screen
const float X0 = EsploraTFT.width()/2.0;
const float Y0 = EsploraTFT.height()/2.0;

// and the limit values for the accelerometer
// good values not considering the acceleration impressed
// to Esplora are those (you can try also the values after comment)
int xAccMin = -180; // -150;
int xAccMax = 180; //170;
int yAccMin = -180; //-147;
int yAccMax = 180; //190;
int zAccMin = -180; //-150;
int zAccMax = 180; //170;

// we need also to save in a global variable the last angle
float lastTanAngle;
float lastZIncl;

// declare an union to convert from float to an array of bytes
// to send them to the serial port
union FLOAT2BYTE {
  float myFloat;
  byte byte_s[4];
} S_FLOAT;


// this function will be executed once at the beginning
void setup() {
  // we need to initialize the display
  EsploraTFT.begin();
  
  // and to select the color of the background
  EsploraTFT.background(0,0,0); // black for an higher contrast
  
  // begin the serial comunication
  Serial.begin(9600);
  // send a byte to establish contact until receiver responds
  establishContact(); 
}

// this will run over and over 
void loop() {  
  // we need to read the Accelerometer values...
  int xAxis = Esplora.readAccelerometer(X_AXIS);
  int yAxis = Esplora.readAccelerometer(Y_AXIS);
  int zAxis = Esplora.readAccelerometer(Z_AXIS);
  
  // ...and to remap them in a fixed range scale
  const int scale = 1000;
  float xIncl = map(xAxis, xAccMin, xAccMax, -scale, scale);
  float yIncl = map(yAxis, yAccMin, yAccMax, -scale, scale);
  float zIncl = map(zAxis, zAccMin, zAccMax, scale, -scale);
  
  // horizontal inclination
  float horizontalAngle = atan2(xIncl, yIncl);
  // vertical inclination
  float verticalInclination = atan2(yIncl, -zIncl);
  
  // print these values to the serial port
  sendFloat(horizontalAngle);
  sendFloat(verticalInclination);

  
  // no we can graph the values in the tft screen
  // this value represent the offset of the line
  // which represent the ground
  float zOffset = map(zAxis, zAccMin, zAccMax, Y0, -Y0);
  // this represent the inclination respect the horizon
  float tanAngle = xIncl/yIncl;

  // first of all we have to delete the previous lines
  // drawing black lines over them
  // horizontal inclination
  EsploraTFT.stroke(0,0,0); // we draw black over the previous lines
  EsploraTFT.line(0, -X0*lastTanAngle+Y0, 2*X0, X0*lastTanAngle+Y0);
  // vertical inclination
  EsploraTFT.line(0, -X0*lastTanAngle+lastZIncl+Y0,
    2*X0, X0*lastTanAngle+lastZIncl+Y0);

  // now we can write the new lines
  // one for horizontal inclination
  EsploraTFT.stroke(0,255,0); // this line would be green
  EsploraTFT.line(0, -X0*tanAngle+Y0, 2*X0, X0*tanAngle+Y0);
  // this line would be red
  // and one for vertical
  EsploraTFT.stroke(255,0,0);
  EsploraTFT.line(0, -X0*tanAngle+zOffset+Y0, 2*X0, X0*tanAngle+zOffset+Y0);
  
  // we will save the values for the next loop iteration
  lastTanAngle = tanAngle;
  lastZIncl = zOffset;
  
  // a little delay for stability
  delay(100);
}

void sendFloat(float floatToSend) {
  // we can send a float to serial port
  S_FLOAT.myFloat = floatToSend;
  for(int ii = 0; ii < 4; ii++) {
    // we have to write bytes on serial port
    Serial.write(S_FLOAT.byte_s[ii]);
  }
}

void establishContact() {
  // save the start time
  unsigned long startTime = millis();
    // until we have a response from the pc
  while (Serial.available() <= 0) {
    Serial.print('A');   // send a capital A
    // if we are waiting from more than 10 seconds
    if(millis() - startTime > 10000) {
      // we will not comunicate with computer
      break;
    }      
    delay(300);
  }
}


kor1989

#4
Sep 07, 2013, 05:19 pm Last Edit: Sep 07, 2013, 05:26 pm by kor1989 Reason: 1
And this is the Processing code that permits the communication with Arduino Esplora.
Quote

/*
 created by Corrado Possieri on 7/09/2013
*/

// import the serial library of processing
// for serial comunication
import processing.serial.*;

// rotation angles (global variables because they are updated in
// the serialEvent function
float rotateY = 0;
float rotateX= PI/3;

// global variables for serial comunication
boolean firstContact = false;
int[] serialInArray = new int[8];
int serialCount = 0; // number of bytes received

// declare the serial port
Serial myPort;

void setup() {  
 // decide the size of the window
 size(800,650,OPENGL);
 
 // list of serial ports avaliable
 println("Serial ports available");
 println(Serial.list());
 // we have to choose the Arduino one
 String portName = Serial.list()[0];
 // connect to this serial port
 myPort = new Serial(this, portName, 9600);
}

void draw () {
 // selection of the background
 background(150, 255, 150);
 // iinsert a white light
 directionalLight(255, 255, 255, 0, 1, -1);
 // we don't want any line
 noStroke();
 
 // go a little back to have a better view
 translate(400,325,-150);
 // rotations comunicated by Arduino
 rotateX(rotateX);
 rotateY(rotateY);

 // draw the floor
 pushMatrix();
 translate(0,-318,0);
 // draw a little reference system
 sistRif(50);
 // select the color of the floor
 fill(31,8,250);
 // save actual reference system
 pushMatrix();
 // draw the floor like a box
 translate(0,0,-50);
 box(5000,5000,100);
 // return to the previous reference system
 popMatrix();
 // draw some lines on the floor to have a better view
 stroke(0);
 for(int kkk=-2500; kkk<=2500; kkk=kkk+100) {
   line(kkk, -2500, 0, kkk, 2500, 0);
   line(-2500, kkk, 0, 2500, kkk, 0);
 }
 popMatrix();
}

void sistRif (float length)
{
 // draw a reference system to better understand
 // what you have done
 strokeWeight(3);
 stroke(255,0,0);
 line(0,0,0,length,0,0); // x
 stroke(0,255,0);
 line(0,0,0,0,length,0); // y
 stroke(0,0,255);
 line(0,0,0,0,0,length); // z
 noStroke();
}

// when datas are available on the serial port
void serialEvent(Serial myPort) {
 // read the byte arrived
 int inByte = myPort.read();
 // if this is the first byte clear the serial port, we have had
 // the first contact, and give this information to Arduino
 if (firstContact == false) {
   if (inByte == 'A') {
     myPort.clear();  // clear the serial port
     firstContact = true;  // connection done
     myPort.write('A'); // wait
   }
 } // if we have already had a connection...
 else {
   // ...add the last byte received to an array
   serialInArray[serialCount] = inByte;
   serialCount++;
     println(serialInArray);
     println();

   if (serialCount > 7) {
     // decode received bytes to obtain 2 floats
     int asInt1 = (serialInArray[0] & 0xFF)
           | ((serialInArray[1] & 0xFF) << 8)
           | ((serialInArray[2] & 0xFF) << 16)
           | ((serialInArray[3] & 0xFF) << 24);
     rotateY = Float.intBitsToFloat(asInt1);
     println(rotateY);
           
     int asInt2 = (serialInArray[4] & 0xFF)
           | ((serialInArray[5] & 0xFF) << 8)
           | ((serialInArray[6] & 0xFF) << 16)
           | ((serialInArray[7] & 0xFF) << 24);
     rotateX = Float.intBitsToFloat(asInt2);
     println(rotateX);
     
     // Reset serialCount
     serialCount = 0;
   }
 }
}



Excuse me but i had to divide the message into tho halves because it was too long.
In the previous message i also attached two screenshot of the Processing code.
Always hoping this will help
Happy sketching

Go Up
 


Please enter a valid email to subscribe

Confirm your email address

We need to confirm your email address.
To complete the subscription, please click the link in the email we just sent you.

Thank you for subscribing!

Arduino
via Egeo 16
Torino, 10131
Italy