Scara Arm forward kinematic equation simulator

Source code :

App made using processing version 3 for windows.


float l1 = 12;  //length of l1
float l2 = 9.7; //length of l2

float l1_scaled = 0;
float l2_scaled = 0;

float l_total;



int width = 650;
int height = 650;

int centerX = width/2;
int centerY = height/2;

int circle_diameter = (width - 75);



float angle;

void setup() {
  size(650,650);
  background(0);
  
  l_total = l1+l2;
  l1_scaled = (circle_diameter/2)*(l1/l_total);
  l2_scaled = (circle_diameter/2)*(l2/l_total);
  
  
}

void draw() {
  background(255,106,0);
  stroke(255);
  
 
  noFill();
  ellipse(centerX, centerY,circle_diameter,circle_diameter);
  line((width/2), 0, (width/2), height); 
  line(0, (height/2), width, (height/2));
  
  float s_ang, a_ang;
  
  float ret_vals[] = new float[2];
  float x1y1_vals[] = new float[2];
  ret_vals = mouseXY_2_unitXY();
  s_ang = calc_shoulder_ang(ret_vals[0], ret_vals[1]);
 
  x1y1_vals = draw_shoulder(s_ang, l1_scaled);
  
  
  
  a_ang = calc_arm_ang(ret_vals[0], ret_vals[1]);
  draw_arm(x1y1_vals[0], x1y1_vals[1], a_ang, l2_scaled, s_ang); 
  
  text("END EFFECTOR XY", 35,85);
  text("X = " + ret_vals[0], 50,100);
  text("Y = " + ret_vals[1], 50,120);
  
  text("S = " + s_ang + "degrees",50,(height-50) );
  text("E = " + a_ang + "degrees",50,(height-30) );
  
  
}

float calc_shoulder_ang (float x, float y){
  float shoulder_angle, yx_div, q_ang;
  yx_div = (float)y/x;
  q_ang = acos( (x*x + y*y + (l1_scaled*l1_scaled) - (l2_scaled*l2_scaled)) / ((2*l1_scaled)*sqrt(x*x + y*y)) );
  
  shoulder_angle = degrees(atan(yx_div) -q_ang);
  
  return shoulder_angle;
  
}

float[] draw_shoulder(float ang, float l1_scaled){
  float angle = radians(ang);
  float[] xy_vals= new float[2];
  float x,y;
  
  x = cos(angle) * l2_scaled;
  y = sin(angle) * l2_scaled;
 
  line(centerX, centerY, (centerX + x), (centerY -y) ); //-y due to x-y co-ord system
  
  
  xy_vals[0] = centerX + x  ;
  xy_vals[1] = centerY -y;
  return xy_vals;
  
}

float calc_arm_ang (float x, float y) {
  float arm_angle;
  arm_angle = degrees( acos( (x*x + y*y -(l1_scaled*l1_scaled) -(l2_scaled*l2_scaled)) / (2*l1_scaled*l2_scaled) ) );
  
  return arm_angle;
  
  
  
}

float draw_arm(float xpos, float ypos, float a_ang, float l, float shoulder_ang){
  float arm_angle = radians(shoulder_ang + a_ang);
  float x,y;
  x = cos(arm_angle) * l2_scaled;
  y = sin(arm_angle) * l2_scaled;
  line(xpos, ypos, (xpos +x), (ypos - y)); //-y due to x-y co-ord system
  
  
  return angle;
  
}


void draw_line(float xpos, float ypos, float ang, float l){
  float angle = radians(ang);
  float x,y;
  x = cos(angle) * 100;
  y = sin(angle) * 100;
  line(xpos, ypos, (xpos +x), (ypos - y)); //-y due to x-y co-ord system
 
  
}







void draw_all(int effector_x, int effector_y) {
  
    
}

float[] mouseXY_2_unitXY(){
  float[] coords= new float[2];
  coords[0] = mouseX - (width/2);
  coords[1] = (height/2) - mouseY;
  return coords;
  
}
  




















Look at this diagram to get an idea of what the S and E angles are:
scara_sketch

Forward Kinematic Equations:

Forward kinematic equations

Forward kinematic equations

Diagram and equations source : https://roboted.wordpress.com/fundamentals/

Posted in Ideas, Processing, scara | 2 Comments

Connecting sensors to the internet using an arduino and a raspberry pi

As part of the PlantBot project, I wanted a way to look at sensor data over the internet. These sensors are moisture, light and pressure. The main one is moisture, the other two were just added in because I had the parts lying around.
Here is a block diagram outlining each of the steps to go from reading the analog sensor values to graphing them on a webpage:

internet-connected-sensor-block-diagram

internet-connected-sensor-block-diagram

Step 1: Reading sensor values with arduino and sending them over UART:

Sensors used:
-LDR
-MPX4115A Pressure Sensor
-Moisture Sensor

I made the moisture sensor using some galvanised nails. First just solder some wires to the top of the nails. Then cover most of the nail with heatshrink, just leaving the tips exposed.

IMG_20160110_152054[1]
IMG_20160110_152033[1]

The arduino nano has a USB-Serial converter on board so it can be plugged directly into the pi via usb and start sending serial data.

Code:

This arduino program waits to receive a serial character from the pi. Once received it will read all of the sensors and send back the sensor values to the pi via uart.

Step 2: Reading sensor values with Python and placing them in a MySQL database:

#!/usr/bin/python

import serial 
import MySQLdb
import time

db = MySQLdb.connect(host="66.147.244.233",    
                     user="wattnoti_user",        
                     passwd="fakepass123", 
                     db="wattnoti_plantbot")        

cur = db.cursor()


port = serial.Serial("/dev/ttyUSB0", baudrate = 9600,timeout=None)
port.flushInput()	   

PressureVal = 0;
MoistureVal = 0;
LightVal = 0;

vals = []

while (port.inWaiting()==0):  #keep sending char until arduino replies
	port.write("*")
	time.sleep(1)
	
vals = (port.readline()).split(',')
print vals
PressureVal = int(vals[0])
LightVal    =  int(vals[1])
MoistureVal = int(vals[2])
cur.execute("insert into sens_vals(Pressure,Light,Moisture) values(" + str(PressureVal) + "," + str(LightVal) +
									"," + str(MoistureVal) + ")" ) #put adc values in mysql db
	

cur.execute("SELECT * from sens_vals")

#dataset = cur.fetchall()  for debugging - print mysql rows to check sensor values were added	
#for row in dataset:	
#	print row
	

db.close()
	
	

The MySQL database was made using the terminal on the pi. Here are some pictures of the database format:

mysql-fields

mysql-fields

sens-vals-table

sens-vals-table

On the Pi, a cronjob is used to run the python script every 30 mins. To edit the crontab, I used sudo crontab -e and entered the following:

*/30 * * * * python /home/pi/plantbot/serial2db.py

This means that every 30 mins the sensors are read and their values placed in the MySQL database.

Step 3 : Running PHP on the server to graph values from MySQL database:

<?php // content="text/plain; charset=utf-8"

define('__ROOT__', dirname(dirname(__FILE__))); 
require_once ('../tools/jpgraph/src/jpgraph.php');
require_once ('../tools/jpgraph/src/jpgraph_line.php');
require_once ('../tools/jpgraph/src/jpgraph_error.php');
require_once ('../tools/jpgraph/src/jpgraph_date.php');

$dates= array();
$light = array();
$pressure = array();
$moisture = array();
$i = 0;

$con=mysqli_connect("66.147.244.233","wattnoti_user","physics","wattnoti_plantbot");
 //Check connection
if (mysqli_connect_errno()) {
  echo "Failed to connect to MySQL: " . mysqli_connect_error();
}
 
mysqli_query($con,"set time_zone = '+00:00'");
$result = mysqli_query($con,"(SELECT * FROM sens_vals ORDER BY id DESC LIMIT 25) ORDER BY id ASC");

while($row = mysqli_fetch_array($result)) {
	$dates[$i] = strtotime($row["date"]);
	$light[$i] =  $row["Light"];
	$pressure[$i] =  $row["Pressure"];
	$moisture[$i] =  $row["Moisture"];
	$i++;
	
}


mysqli_close($con);


$graph = new Graph(800,500);
$graph->img->SetMargin(40,40,40,40);	
$graph->img->SetAntiAliasing();
$graph->SetScale("datlin");
$graph->SetShadow();
$graph->title->Set("PlantBot Sensor Readings");
$graph->title->SetFont(FF_FONT1,FS_BOLD);
// Ensure anti-aliasing is off. If it is not, you can SetWeight() all day and nothing will change.
$graph->img->SetAntiAliasing(false);
$graph->xaxis->SetLabelAngle(45);
$graph->xaxis->scale->SetDateFormat('Y:M:d:D:H:i');
$graph->legend->SetPos(0.37,0.07,'right','center');
$graph->legend->SetFrameWeight(2);
$graph->legend->SetColor('black','black');
$graph->xgrid->Show(true,false);
// Use 20% "grace" to get slightly larger scale then min/max of
// data
$graph->yscale->SetGrace(0);

$graph->yaxis->title->Set("ADC Value");
$graph->yaxis->SetTitleMargin(-700);

$p1 = new LinePlot($light,$dates);
$p1->SetColor("blue");
$p1->SetCenter();
$p1->SetLegend("light");

$p2 = new lineplot($pressure,$dates);
$p2->setColor("orange");
$p2->SetLegend("pressure");

$p3 = new lineplot($moisture,$dates);
$p3->setColor("yellow");
$p3->SetLegend("moisture");

$graph->Add($p1);
$graph->Add($p2);
$graph->Add($p3);

$p1->SetWeight(3);
$p2->SetWeight(3);
$p3->SetWeight(3);

$graph->Stroke();


?>

This PHP program looks kinda bulky but most of it is just jpgraph stuff to make the graph look nice. Lines 1-34 is where the MySQL db is accessed and the sensor values read in PHP arrays.

Graph Produced (Real time image):

I’m still working out some of the kinks with jpgraph so while it’s not perfect, you get the idea.
The html page I’ll be displaying all of the real time data on is located at http://wattnotions.com/html_stuff/PlantBotNet.html
As I’m writing this post now (10th January 2016), all it contains is a picture of the graph – I’ll be adding to it in the near future.

Update 1 : (10th Jan 2016)
IMG_20160110_162350[1]
Just planted some cress seeds in part of this plantbox I have – will manually water it (uh effort) for the next few days/weeks or however long it takes for cress seeds to grow. This will be automated soon enough by Plantbot. Stay tuned!

Posted in Arduino, Atmel, how to, Microcontrollers, PHP, Projects, Python | Tagged , , | Leave a comment

atmega16u2 virtual serial example using LUFA Library

Sending data from a microcontroller is a pretty common requirement in a lot of the projects I work on. One way of doing it is sending serial data out from the uC to a serial to usb converter chip to a computer. This has the advantage of involving very little code overhead for both the uC and the computer. It does also make it more difficult to route on a PCB (especially trying to fit it onto a single layer) and of course you have to pay for the serial/usb converter chip which in my experience range from about 2.50 to 5 euro per chip. An alternative to this is to have the uC communicate directly via usb with the computer. This can be done on a uC entirely in software – the V-USB library for atmel microcontrollers allows almost any atmel micro to communicate via usb. This creates a large CPU overhead as most of the uC’s time is spent maintaining the USB connection – leaving little time for anything else. uC’s with USB hardware in them offset this problem to a certain extent by including dedicated USB hardware so less CPU time is needed to use USB. The LUFA (Lightweight USB Framwork for AVRs) is a library aimed at taking advantage of this USB hardware. It comes with loads of examples that work with several types of atmel chips. The one that I chose is the atmega16u2 because it was pretty cheap and it was used the arduino uno as the usb-serial converter for the board. This meant that there was schematics of the board layout available online which came in very hany for making my own board. This board was intended to be used as part of the PlantBot project I’m working on but it ended up just being a LUFA virtual serial test board. Here are some pics of the board:

atmega16u2-virtual-serial-lufa-board

atmega16u2-virtual-serial-lufa-board

atmega16u2-virtual-serial-lufa-board-PCB

atmega16u2-virtual-serial-lufa-board

What I wanted the LUFA library to do was pretty specific – the atmega16u2 should show up as a virtual serial port so that the computer can connect and read data from it like any other serial port. All of the other ways of communicating over USB eg HID etc wouldn’t do it. There was one example that came with LUFA that fit the bill – VirtualSerial. There were a few problems with getting this example to run on the atmega16u2 so I’ll document them and what the fix was.

First problem was the compiler giving out about an undefined reference to the function clock_prescale_set(clock_div_1);
This turned out to be an avr-gcc problem. The power.h file (link to reference manual) didn’t have the atmega16u2 listed in one of it’s conditions include lines. There is a part in the file that looks like this:

#if defined(__AVR_AT90CAN32__) \
|| defined(__AVR_AT90CAN64__) \
|| defined(__AVR_AT90CAN128__) \
|| defined(__AVR_AT90PWM1__) \
|| defined(__AVR_AT90PWM2__) \
|| defined(__AVR_AT90PWM2B__) \
|| defined(__AVR_AT90PWM3__) \

and it had the atmega16u4 but not the u2 version so I just added it in and all was good. If you are looking for this file, on my pc it is located at C:\WinAVR-20100110\avr\include\avr\power.h and to find the relevant part of the file do a search for the following: clock_div_1 = 0,

The next problem was that this virtual serial example was based around a seperate usb joystick example. This joystick example would read input from certain pins and send a certain string over usb. The problem was that this example doesn’t work with the atmega16u2 because it uses PORTE all over the place in its code and the 16u2 doesn’t have a PORTE. The compiler was not happy and since this problem was spread over several include files I decided to just remove all joystick related code and just have the virtual serial send over a string on a loop (“testing123″ in case you were wondering). After all of the joystick butchering the example finally compiled – I plugged in the board and it was recognised as a usb device. It turns out that for the VirtualSerial to work in windows you have to install drivers for it. the driver file is in the VirtualSerial example folder of the lufa library. After installing the driver everything was hunky dory, I used putty to check the serial data coming in.

So it’s a big thumbs up for the LUFA library – it’s nice have just a chip and a usb port on a PCB and having it send serial data to a computer!

The PCB schematic and board files as well as the modified VirtualSerial example (joystick-less) is all available for download here. The PCB was designed in KiCad.

Click image for PDF of schematic:

atmega-16u2-schematic-lufa

atmega-16u2-schematic-lufa

Board layout:
brd

Posted in Atmel, Hardware, Microcontrollers, PCBs | Tagged , , | Leave a comment

Making a USB Powered LED Bird Lamp


Drawings:


rect5018

Download svg file here

Download code here


Extra Info:


LED strip used is ws2812b. Adafruit neopixel library ‘buttoncycler’ program lightly modified to work with a potentiometer. The peacock image was found via google images. link to the pinterest page I got it from.

Posted in Arduino, how to, Ideas, Inkscape, laser cutter, Projects | Tagged , , | 2 Comments