Friday, August 25, 2017

processing language code to serially receive ADXL345 raw data in CSV format and plot them as real-time-graph


import processing.net.*;
//import processing.serial.*;
Client ennodaClient;
//Serial envazhi;
int nikazhmadhippu1, nikazhmadhippu2, nikazhmadhippu3;
int z=20;

int[] akalavu;
int[] meiyalavu;
int[] uyiralavu;

int[] akmin;
int[] uyirmin;
int[] meimin;
int akminn,akmaxx;
int uyirminn, uyirmaxx;
int meiminn, meimaxx;


int[] akmax;
int[] uyirmax;
int[] meimax;

int ullpiri;
int h=1;

//PrintWriter actual,mapped,simulate;


void setup()
{
  size(displayWidth, displayHeight);
  //size(1000, 550);
  frameRate(60);
   
  strokeWeight(1);
  smooth(); // or noSmooth();
  akalavu = new int[100];
  meiyalavu = new int[100];
  uyiralavu = new int[100];
 
   akminn = 2000;
   meiminn = 2000;
   uyirminn = 2000;
   akmaxx = -1000;
   meimaxx= -1000;
   uyirmaxx= -1000;
  
 
 
  ennodaClient = new Client(this, "120.120.120.120", 265);
 
  //String portName = Serial.list()[1];
 // envazhi = new Serial(this, portName, 38400);
 // actual = createWriter("unmai_actualvalues.txt");
 // simulate = createWriter("mapped_for_simulation.txt");
 // mapped = createWriter("marupadhippu_mappedvalues.txt");

}

void draw()
{
 
  String ull = ennodaClient.readStringUntil('\n');
  //String ull = envazhi.readStringUntil('\n');
 

  if(ull != null)
  {
     
   int[] ullpiri = int(split(ull, ","));
  
   nikazhmadhippu1 = int(ullpiri[0]);
   nikazhmadhippu2 = int(ullpiri[1]);
   nikazhmadhippu3 = int(ullpiri[2]);
  //  println("nikazh =", nikazhmadhippu1);
   background(255);
   akalavu[1]= nikazhmadhippu1;
   meiyalavu[1]= nikazhmadhippu2;
   uyiralavu[1]= nikazhmadhippu3;
 
   
   /*actual.print(h);
   actual.print("]");
   actual.print(akalavu[1]);
   actual.print(",");
   actual.print(meiyalavu[1]);
   actual.print(",");
   actual.print(uyiralavu[1]);
   actual.println();*/
    
  
   {
   
  
     for(int i = 1; i < 100; i++)
        {
         
          akalavu[i-1] = akalavu[i]; //shifting every value to previous array-element ANDDDDDDDDD storing 100 subsequent values in  100 array-elements
          meiyalavu[i-1] = meiyalavu[i];
          uyiralavu[i-1] = uyiralavu[i];
         
          akminn = min(akminn, akalavu[i]);
          meiminn = min(meiminn, meiyalavu[i]);
          uyirminn = min(uyirminn, uyiralavu[i]);
         
          akmaxx = max(akmaxx, akalavu[i]);
          meimaxx = max(meimaxx, meiyalavu[i]);
          uyirmaxx = max(uyirmaxx, uyiralavu[i]);
         
        /*  if ( akalavu[i] < akmin[i]){akmin[i] = akalavu[i]; akminn = akmin[i];}
          if ( meiyalavu[i] < meimin[i]){meimin[i] = meiyalavu[i]; meiminn = meimin[i];}
          if ( uyiralavu[i] < uyirmin[i]){uyirmin[i] = uyiralavu[i]; uyirminn = uyirmin [i];}*/
         
         // println("ak =",akalavu[i]);
        //  println(meiyalavu[i]);
         // println("a =",uyiralavu[i]);
      
       /*simulate.print(akalavu[i]);
       simulate.print(",");
       simulate.print(meiyalavu[i]);
       simulate.print(",");
       simulate.print(uyiralavu[i]);
       simulate.println();*/
      
        }
   akalavu[100-1] = int( map(nikazhmadhippu1, akminn, akmaxx, 0, height/2));
   meiyalavu[100-1] = int( map(nikazhmadhippu2, meiminn, meimaxx,  height/2, height));
  // uyiralavu[100-1] = int( map(nikazhmadhippu3, uyirminn, uyirmaxx, 0, height));
   
  /* mapped.print(h);
   mapped.print("]");
   mapped.print(akalavu[99]);
   mapped.print(",");
   mapped.print(meiyalavu[99]);
   mapped.print(",");
   mapped.print(uyiralavu[99]);
   mapped.println();*/
  
  
  }
    {     
     beginShape();
      strokeWeight(1);
      stroke(0, 0, 250); //(rgb) colored lines, blue for z-axis
      {
       int j=1;
       int i=1;
      //plotting allllllllllllllllll 100 array-elements in x-y graph here.       
      // variable-i gives 100 numbers of array-elements which are plotted on the y-axis; variable-j gives the x-axis position.
      // variable z helps to increase or decrease the x-axis-gap between 2 successive inputs.
       for (i=1, j=1; i<99 && j <(z*100); i++, j= j+z)
        {                                             
         curveVertex(j, akalavu[i-1]); //as the loop runs, on every loop a single vertex-point is fixed in the display-window-matrix and....on next loop another vertex-point is fixed. and those 2 points get linked by a curve.
         
        }                             //this logic of curve-fitting between 2 successive points continues till the end of THIS "for" loop, resulting in the curve-plot.
     
      }
     endShape();    
    }
   
    //x-axis
     /* {     
      beginShape();
      strokeWeight(1);
      stroke(0, 250, 0); //green for x-axis
       {
       int j=1;
       int i=1;
     
       for (i=1, j=1; i<99 && j <(z*100); i++, j= j+z)
        {                                             
          curveVertex(j, uyiralavu[i-1]); //as the loop runs, on every loop a single vertex-point is fixed in the display-window-matrix and....on next loop another vertex-point is fixed. and those 2 points get linked by a curve.
                
        }                            
   
       }
      endShape();    
      }*/
     
    //y-axis 
      {     
      beginShape();
      strokeWeight(1);
      stroke(250, 0, 0); //red for y-axis
       {
       int j=1;
       int i=1;
    
       for (i=1, j=1; i<99 && j <(z*100); i++, j= j+z)
        {                                             
      
         curveVertex(j, meiyalavu[i-1]);
         
        }                            
      
       }
      endShape();    
      }
     
               
  
  }

// nEram();
  //framerate();
 name();

 h++;
}

void name() {
  PImage padam1, padam2, padam3, padam4, padam5, padam6, padam7, padam8, padam9, padam10, padam11;
  //fill(80, 80, 200);
  //text ("m.rajaguru", 1550, 30);
  //fill(255, 255, 255);
  //padam2 = loadImage("enperu.png");
  //image(padam2, 1000, 0, 129, 29);
  padam1 = loadImage("jalli3.png");
  image(padam1, 5, 5, 108, 115);
 // padam3 = loadImage ("rate.png");
 // image(padam3, 215, 15, 325, 28);

  padam4 = loadImage ("count2.png");
  image(padam4, 158, 10, 292, 25);
 // padam5 = loadImage ("duration.png");
 // image(padam5, 200, 68, 340, 28);
//  padam6 = loadImage ("time.png");
//  image(padam6, 333, 93, 207, 26);
  padam7 = loadImage ("axes.png");
  image(padam7, 113, 5, 108, 115);
 // padam4 = loadImage ("count2.png");
  //image(padam4, 178, 5, 292, 25);

 // padam8 = loadImage ("19200.png");
  //image(padam8, 1500, 48, 73, 24);
 //padam9 = loadImage ("14400.png");
  //image(padam9, 22,10, 73, 24);
  //padam10 = loadImage ("9600.png");
  //image(padam10, 1500, 96, 73, 24);
  //padam11 = loadImage ("vellalavu.png");
 // image(padam11, 1482, 5, 108, 43);
 
  //image(padam2, 0, 230, 100, 20);
 

}

void nEram(){
  fill(180, 0, 0);
  int maNi = hour();
  int nimidam = minute();
  int nodi = second();

  text (maNi, 550,110);
  text (": "+ nimidam, 570, 110);
  text ( " : " + nodi, 590, 110);
  text ("hrs", 620,110);
 // text (nikazhmadhippu, 550, 535);

}

void framerate(){
  text (frameRate, 546, 33);
 
  //text ("frame-eNNikkai / count:", 500, 55);
  //text ("Odum-nEram, nodiyil //running-duration, sec: ", 380, 40);
  text (frameCount, 550, 60);
  text (millis()/1000, 550, 85);
  fill(255, 255, 255);
 
}

/*void keyPressed() {
  if ((key == 'v') || (key == 'V'))
   {
    actual.flush();  // Writes the remaining data to the file
    actual.close();  // Finishes the file
    mapped.flush();
    mapped.close();
    simulate.flush();
    simulate.close();
    exit();  // Stops the program
   }
}*/

 

arduino code to read ADXL345 and to send the data to PC serially

// Cabling for i2c using Sparkfun breakout with an Arduino Uno / Duemilanove:
// Arduino <-> Breakout board
// Gnd      -  GND
// 3.3v     -  VCC
// 3.3v     -  CS
// Analog 4 -  SDA
// Analog 5 -  SLC
//https://github.com/jenschr/Arduino-libraries/blob/master/ADXL345/examples/ADXL345_no_library/BareBones_ADXL345.pde



#include <Wire.h>

#define DEVICE (0x53) // Device address as specified in data sheet

byte _buff[6];

char POWER_CTL = 0x2D;  //Power Control Register
char DATA_FORMAT = 0x31;
char FIFO_CTL = 0x38;
char BW_RATE = 0x2C;
char DATAX0 = 0x32; //X-Axis Data 0
char DATAX1 = 0x33; //X-Axis Data 1
char DATAY0 = 0x34; //Y-Axis Data 0
char DATAY1 = 0x35; //Y-Axis Data 1
char DATAZ0 = 0x36; //Z-Axis Data 0
char DATAZ1 = 0x37; //Z-Axis Data 1

void setup()
{
  Wire.begin();        // join i2c bus (address optional for master)
  Serial.begin(250000);  // start serial for output. Ensure Serial Monitor at same rate
 // Serial.print("init");
 
  //Put the ADXL345 into +/- 2G range by writing the value 0x01 to the DATA_FORMAT register.
  writeTo(DATA_FORMAT, 00001000);
  writeTo(FIFO_CTL, 10000000);
  writeTo(BW_RATE, 00001111);
  //Put the ADXL345 into Measurement Mode by writing 0x08 to the POWER_CTL register.
  writeTo(POWER_CTL, 0x08);
 
}

void loop()
{
  readAccel(); // read the x/y/z tilt
  delay(100); // only read every 0,5 seconds
}

void readAccel() {
  uint8_t howManyBytesToRead = 6;
  readFrom( DATAX0, howManyBytesToRead, _buff); //read the acceleration data from the ADXL345

  // each axis reading comes in 10 bit resolution, ie 2 bytes.  Least Significat bit first!!
  // thus we are converting both bytes in to one int
  int x = (((int)_buff[1]) << 8) | _buff[0];  
  int y = (((int)_buff[3]) << 8) | _buff[2];
  int z = (((int)_buff[5]) << 8) | _buff[4];
 // Serial.print("x: ");
  Serial.print( x );
  Serial.print(",");
  Serial.print( y );
  Serial.print(",");
  Serial.println( z );
}

void writeTo(byte address, byte val) {
  Wire.beginTransmission(DEVICE); // start transmission to device
  Wire.write(address);             // send register address
  Wire.write(val);                 // send value to write
  Wire.endTransmission();         // end transmission
}

// Reads num bytes starting from address register on device in to _buff array
void readFrom(byte address, int num, byte _buff[]) {
  Wire.beginTransmission(DEVICE); // start transmission to device
  Wire.write(address);             // sends address to read from
  Wire.endTransmission();         // end transmission

  Wire.beginTransmission(DEVICE); // start transmission to device
  Wire.requestFrom(DEVICE, num);    // request 6 bytes from device

  int i = 0;
  while(Wire.available())         // device may send less than requested (abnormal)
  {
    _buff[i] = Wire.read();    // receive a byte
    i++;
  }
  Wire.endTransmission();         // end transmission
}

code for ESP01 to setup an ACCESS POINT etc.....

#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>

#define MODE_AP

const char *ssid = "adhirvu_alavi";  //hotspot's name
const char *pw = "kathirnilavan"; //hotspot's password
IPAddress ip(120, 120, 120, 120); //hotspot's IP
IPAddress netmask(255, 255, 255, 0);
const int port = 265; // port#

WiFiServer server(port);
WiFiClient client;

uint8_t buf[1024];
uint8_t x = 0;

void setup() {
  delay(500);
  Serial.begin(250000);
  WiFi.mode(WIFI_AP);
  WiFi.softAPConfig(ip, ip, netmask);
  WiFi.softAP(ssid, pw);
  server.begin(); // start TCP server

}

void loop() {

  if (!client.connected()) { // if client not connected
    client = server.available(); // wait for it to connect
    client.setNoDelay(1);
    return;
  }

  if (Serial.available()) {
    while (Serial.available()) {
      buf[x] = (char)Serial.read(); // reading from arduino serial....
      if (x < 1023) x++;
    }
    //data to client.....
    client.write((char*)buf, x);
    x = 0;
  }

}



video:
 

Thursday, August 17, 2017

prototype - mould oscillation checker: part-2

the first part goes here, that gives a brief intro about this prototype.
https://tech-steel.blogspot.in/2016/01/prototype-mould-oscillation-checker.html
mould acceleration tracking

ADXL335 is an analog sensor with a measurement range of +/- 3G-forces. but the vibrations were much smaller to be sensed by this longer range; so had to select a sensor with lesser G-force range, so that feeble vibrations can also be measured.

ADXL345 provides a user selectable range starting with a minimum of +/-2G-forces. this is a digital sensor with different registers providing controls. these registers can be accessed through arduino coding.

arduino microcontroller accesses data registers of ADXL345 to collect data, bundles the data into CSV format, and sends them serially to PC through USB or to wifi-module(ESP01). this wifi module transfers the same data to any connected client.

USB data transfer takes advantage of the inbuilt USB-to-serial converter of the arduino board. but wifi  feature needs to be added separately. ESP8266 based wifi modules are fast catching up the market as IoT devices.

ESP01 is one of the many variants of ESP8266, with just 2 GPIO pins exposed on the breakout board. codes can be written in many languages, like lua scripts, micro-python, baremetal C/C++...but those are not amateur friendly. so i chose arduino-IDE with the supporting ESP8266-core added into it.

loading code into ESP01 is a bit cumbersome, since the GPIO-0 pin has to be GRouNded before powerup, so that ESP01 enters into programming mode in stead of native-program-run-mode. the following setup has to be made ready first with exactly those wirings, and....plugging that USB-to-TTL converter on USB port of a PC will take ESP01 into programming mode.

once ESP01 goes into programming mode, open up arduino-IDE, select the right settings from tools-menu of the IDE.


ESP01 program-loading setup in breadboard view:

 

actual setup to load ESP01 program follows here.... 





above setup helps us to load a new sketch(program) onto ESP01. the sketch is coded in such a way that, it receives serial data from arduino and transfers the same to any connected wifi-client.

*******************

microcontroller sends data in CSV format to ESP01, and the ESP just sends the same exactly in that CSV format to client.

total setup goes this way, where ADXL345 is connected to arduino, and ESP01-Rx pin is connected to Tx pin of the arduino clone, through a voltage divider arrangement. voltage divider (or a level shifter) is necessary because, ESP01 operates on 3.3v while arduino operates on 5v.

connecting arduino Tx output to ESP01's Rx-input-pin will fry ESP01 sooner or later, but surely at some point of time. all 3 units(arduino uno, ADXL345 &ESP01) are powered from an external powersource. this is a must, because as ESP transfers data in bursts, there's an extremely heavy current fluctuation on the source. so it is better to avoid sourcing power for ADXL345& for ESP01 from arduino.
i have not added capacitors to take care of voltage fluctuations; i will add one between Vcc and GND of ESP before real trials.

*****************

any client must connect to the ACCESS POINT(adhirvu_alavi) generated by ESP01. once connected, there's another program(written in programming language) that receives the data through the specified socket with particular IP(120.120.120.120) & port(265), and presents the raw data in real-time graph format on monitor.

total setup in breadboard view:



following is the actual total-setup.




i made videos of uploading codes on ESP01 & arduino clone, also of graph on monitor; unedited videos are too huge to upload here. i will edit those lengthy videos into short ones, upload them to youtube & will share the links here sooner.

codes:
1. arduino UNO clone needs a code, to scan ADXL345's buffers and get acceleration data. written in arduino IDE.
http://tech-steel.blogspot.in/2017/08/arduino-code-to-read-adxl345-and-to.html

2. ESP01 needs a code, to setup an ACCESS POINT for wifi clients to connect to, to   receive  data from arduino's Tx pin to ESP01's Rx pin & to transfer data from arduino to wifi-client. this was written in arduino IDE, invoking ESPwifi-core into that environ.
http://tech-steel.blogspot.in/2017/08/code-for-esp01-to-setup-access-point-etc.html

3. client (windows-based wifi-device) needs a program (processing language) that can capture the data aired by ESP01, and display that data as a real-time-graph.
http://tech-steel.blogspot.in/2017/08/processing-language-code-to-serially.html

improvements:
1. arduino uno clone runs at 16MHz speed,  while arduino-M0 & arduino-DUE variants run at 48MHz & 84MHz respectively; that is 3&5 times the speed of uno-model. further, in uno instructions are processed in 8bit format, while M0& DUE support 32bit format, thereby the buswidth is also increased.

arduino101 variant brings yet another advantage, combining 32Mhz speed intel-curie module and BMI160 accelerometer in-built on the board. this accelerometer has a minimum range of +/-2G-forces same as ADXL345.

arduino esplora also has an accelerometer (MMA7361) in-built on the board, that measures a range of +/-1.5G-forces. hence sensitivity is improved.

a more sensitive breakout board could be BMA180(bosch made) from sparkfun, but this product has been discontinued.

the most sensitive i found is, ADXL313 with range starting at +/-0.5 G-force, which will measure the lightest of vibrations.

ADXL213/350 could prove helpful with range starting at +/-1.2 G-force.

trials with all the above & any combination of them will burn a big whole not just on my pocket but on my rear too. so...., won't test any of these.

2. in stead of having a separate ESP01, arduino variants with in-built wifi will provide advantages like better stability, smaller footprint, easy coding setups. arduino tian , genuino and yun are also faster boards with in-built wifi feature.


3. to power these up, we need a source that can supply 5v at a rate of at least 1.5 to 2A. wifi data transfer involves a lot of bursts and hence fluctuations on power. tried with AA type batteries in 4S2P arrangement, but that was not at all enough. finally powered from wallsocket(not a truly portable wifi device :-(. ) li-ion or li-polymer batteries are better alternatives, but no time to try them now.

videos:
  
https://youtu.be/jdT8XfH8cqs
https://youtu.be/qPb5NlMKo6k



https://youtu.be/E0pOcwH7neA
https://youtu.be/kHSSvnSYPzk