maandag 10 juni 2013

Component build, and test

After we finally had the detailed design the way we wanted it, it was time to take the next step. This is a step of little steps, but nevertheless steps we must take. The idea behind it is simple, you start designing big, and slowly work it down to details, then when you start building, begin with all the details and put them together until you have the big design.
Our mentality followed 4 steps this phase, 1 we need this information, 2 it seems we can measure that with this sensor, 3 why can't this fancy resistor give me what I want, 4 oh so it works like that, that was easy....
As our orders slowly started to get in, I started to familiarize myself with all the different sensors, buttons, motors, and in the back of my mind I kept trying to put the pieces together in the idea that would become the full robot. Most of the time I was present behind my laptop, a sheet of paper in front of me, and an arudino with some wires at my left side.

What gave me some room to keep figuring how the total would work, is that reading sensors, or controlling motors ain't all that hard, in aruduino a simple "serial read" function suffices, specify where the data comes into the controller, and print it to the interface. With engines basically the same, specify the pin, and analogWrite a PWM signal.

/*
  AnalogReadSerial
  Reads an analog input on pin 0, prints the result to the serial monitor.
  

 This example code is in the public domain.
 */

// the setup routine runs once when you press reset:
void setup() {
  // initialize serial communication at 9600 bits per second:
  Serial.begin(9600);
}

// the loop routine runs over and over again forever:
void loop() {
  // read the input on analog pin 0:
  int sensorValue = analogRead(A0);
  // print out the value you read:
  Serial.println(sensorValue);
  delay(1);        // delay in between reads for stability
}

One component however had some more to it, the Ultra sonic sensors. We bought a parking sensor for implementation in a car, to use it in our robot. This was however a complete system that gave feedback about the detected range via (very annoying) bleeps. So we decided to cut the wires to the speaker, and read the signal it received. Yet as it turned out, it was a mes... 4 sensors all sending their values to a "magic box" which in turn sends a messy signal to the speaker. To overcome this I came up with a simple and relatively successful solution: first, when the sensors detected an object within 45 cm, the signal became constant, outside that range however it where all pulses from the different sensors, so i decided to calculate an average from the pulses that we read (if we did at all) so we could vaguely pinpoint an object in the vicinity. This solution gave us two triggers, the first being a certain certainty that an object is present whiting a range of 90 to 45 cm, the second the unmistakable truth that we are about to collide with an object within 45 cm. In code it looks like this:

#include <RunningAverage.h>
int pin = A0;
unsigned long duration = 0;
int x;
int y;

RunningAverage myRA(10);
int samples = 0;

void setup()
{
  pinMode(pin, INPUT);
  Serial.begin(9600);
   myRA.clear(); 
}

void loop()
{
  x= analogRead(A0);
  
  duration = pulseIn(pin, LOW);
  Serial.print(x);
  Serial.print(" ");
  Serial.print(duration);
  Serial.print(" ");
  
  myRA.addValue(duration);
  samples++;
  Serial.print("Running Average: ");
  Serial.println(myRA.getAverage(), 3);

  if (samples == 30)
  {
    samples = 0;
    myRA.clear();
  }
  delay(100);
}

While testing the different components, I also started working on the first functions, these pieces of code where my "components" as these components combined would make sub-systems, and putting those together formed the code for a slave, or master. So starting with Pick and Place, I divided the sub-system in a couple of components. The hand, the arm, and the scissor lift.

For the hand, this was the first code i wrote:

//luchtkussen/hand
int Flexsensor = 3;
int Ventiel2open = 7;
int Ventiel2dicht = 6;
int range2 = analogRead(2);
int flescounter = 0;

void setup(){
  Serial.begin(9600);
  Ventiel2open = OUTPUT;
  Ventiel2dicht = OUTPUT;
  Flexsensor = INPUT;
}

void loop(){
  
  if(range2 < 256){  //TESTEN EN GOEDE WAARDE VINDEN!
  flescounter = pakfles();
  }
  if (flescounter==1 && range2 < 256){
    flescounter = dropfles();
  }
}

int pakfles(){
  delay(10);
  digitalWrite(Ventiel2open, HIGH);
  digitalWrite(Ventiel2dicht, LOW);
  delay(100); //TESTEN en goede waarde vinden
  
  int flescounter = 1;
  return flescounter;
}

int dropfles(){
  digitalWrite(Ventiel2open, LOW);
  digitalWrite(Ventiel2dicht, HIGH);
  int flescounter = 0;
  return flescounter;
}

The code is based around the valve that triggers the air cushion, and the IR sensor that triggers the process when the had is positioned in range. Even tough this program has quite some errors, it was a great start to get some insight in the declaration and working of all the different sub processes.

For the arm, I wrote this:

//Arm

#include <Servo.h>
Servo myservo;
int Ventielopen = 8;
int Ventieldicht = 9;
int flescounter = 0;

void setup(){
  Serial.begin(9600);
  myservo.attach(5);
  Ventielopen = OUTPUT;
  Ventieldicht = OUTPUT;
  
}

void loop(){
  
  void StartArm();
  delay(200);
  int MoveArm(flescounter);
  delay(200);
  void StopArm();
  delay(200);
  
  flescounter ++;
  if(flescounter == 1){
  flescounter = 0;
  }
}

void StartArm(){
  
  myservo.write(180);
  digitalWrite(Ventielopen, HIGH);
  digitalWrite(Ventieldicht, LOW);
}

int MoveArm(int counter){
  
  switch(counter){
  
  case 0: myservo.write(180);
  break;
  
  case 1: myservo.write(0);
  break;
}
}

void StopArm(){
  
  digitalWrite(Ventieldicht, HIGH);
  digitalWrite(Ventielopen, LOW);
  myservo.write(90);
}

This bit of code is aimed at positioning the hand, by turning the arm to the right side by servo, or extending/retracting the cylinder that  makes the length of the arm. As with the previous code we were no were near testing, because the robot also consisted of components at this time, but it gave me great insight in how the robot would work.

The last bit of code I wrote for P&P in this phase was the scissor lift, aimed at altering the height of the hand.

//motorsturing Schaarlift
int knopmax = 4;
int knopmin = 13;
int IRsensorpin = 2;
int range = analogRead(2);



void setup() {
  Serial.begin(9600);
  knopmax = INPUT;
  knopmin = INPUT;
  IRsensorpin = INPUT;
}

void loop() {

  void SchaarUp();
  delay(200);
  void SchaarDown();
}

void SchaarUp(){
  do{
    analogWrite(10, 192);
  }
  while(knopmax =!1);
}


void SchaarDown(){
  int range = analogRead(2);
  
  do{
    analogWrite(11, 192);
  }
  while(knopmin =! 1 || range < 10);
}

This bit of code was the most reliable I wrote at that time, and it kept this form until the very end, when it refused to work but that is for a later post.

To touch back on the master slave communication, around this time I also wrote the first "template" for the slaves. With the master logic mostly unspecified, I made the first move by designing a simple template the master could "access" to give commands to the slaves.

#include <Wire.h>

int command;
int x;
int c;

void recieveEvent(int howMany);


void setup()
{  
  Wire.begin(x); //nummer van de slave invullen
  Wire.onReceive(recieveEvent);
  Wire.onRequest(requestEvent);
  Serial.begin(9600);
}


void loop()
{
  delay(100);
}


  void recieveEvent(int howMany)  //als de master een opdracht op de bus zet
  {
    while(1<Wire.available())
    {
      int command = Wire.read();
    }
    x= Wire.read();
   
    c=0;
    
    switch(x){
    
    case 01:                       //zelf invullen
    
    c=1;                           //feedback variable
      break;
   
   case 02:                        //zelf invullen
   c=2;
     break;
     
   case 03:                         //zelf invullen
   c=3;
     break;
     
   case 04:                         //zelf invullen
   c=4;
     break;
    }
}
   void requestEvent()      //als de master een status check doet
   {  
     Wire.write(c);
   }
     
This code bases around receiving a command over I2C, and computing the associated task, while storing a feedback bit for the master. However, as turned out, when the master starts serial communication and activates the wire.h library, it is handled as an interrupt for the slave, not to much of a problem since everything is in the interrupt function. However to add another complex, while the slave or master is in the interrupt, the bus is kept busy, and thus cannot start any other communication. This led to a rework in a later stage, but the biggest changes where: computing all the tasks in the main, or functions from the main, and keeping the interrupt as short as possible.






Geen opmerkingen:

Een reactie posten