Things used in this project

Hardware components:
Udooneo trasparent
UDOO NEO
×1
barcode scanner
×1
Servo (generic)
×1
step motor NEMA 17
×1
step motor M35SP-11NK
×1
pololu A4988 stepper driver
×2
826 04
Male/Female Jumper Wires
×6
Male/Male Jumper Wires
×7
Te connectivity   amp 4 103777 0 image 75px
Male Header 80 Position 2 Row (0.1")
×1
Pppc081lfbn rc sml
Female Header 8 Position 1 Row (0.1")
×4
Omron b3f 1000 image 75px
SparkFun Pushbutton switch 12mm
×3
Kingbright wp7113srd d image
5 mm LED: Red
×1
Kingbright wp7113sgd
5 mm LED: Green
×1
Led technology l03r5000q1 image
5 mm LED: Yellow
×1
12V power supply
×1
Software apps and online services:
Ide web
Arduino IDE
Altium Designer 16
CircuitCam
Hand tools and fabrication machines:
LPKF E34 ProtoMat

Schematics

Personal UDOO shield - Schematic
This is the Schematic of our personal shield. Here you can see, named as "JP" the headers of the Pololu driver while "J" stands for the headers of the other components we used. As you can see the "blue" words just represent the names of the NET, while the "red" words represent the effective connections between two or more parts, even if the wire is not represented.
Schematic
Personal UDOO shield - Circuit routing
This is the circuit routing of our shield. In "red", you can see the routing of the top side, in "blue" the routing of the bottom side. The "light blue circles" are some holes used to attach the UDOO board with our shield on the printer casing.
Circuit%20routing
Personal UDOO shield - LPKF Prototype Generator
This is the output file of the program "Circuit Cam" used to convert the circuit routing in a "gerber file", so the LPKF machine can read this file and carve the shield on a sheet of copper, to obtain our shield.
Lpkf%20prototype%20generator

Code

Code for ARM Cortex M4 - ARM Cortex A9 communicationC/C++
This code is used to send messages from A9 side to M4 side. After this program is launched, the A9 processor receives the input values from the bar code reader and then it sends them through the internal serial "/dev/ttyMCC" to the M4 co-processor. Note that a terminal is needed to write the values that have to be sent through the serial, just use the normal GNU/LINUX bash, like "LXTerminal" already installed on the desktop of the UDOO NEO.
#include <termios.h>
#include <fcntl.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
#include <unistd.h>



int set_interface_attribs (int fd, int speed, int parity)
{
        struct termios tty;
        memset (&tty, 0, sizeof tty);
        if (tcgetattr (fd, &tty) != 0)
        {
                printf ("error %d from tcgetattr", errno);
                return -1;
        }

        cfsetospeed (&tty, speed);
        cfsetispeed (&tty, speed);

        tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS8;     // 8-bit chars
        // disable IGNBRK for mismatched speed tests; otherwise receive break
        // as \000 chars
        tty.c_iflag &= ~IGNBRK;         // ignore break signal
        tty.c_lflag = 0;                // no signaling chars, no echo,
                                        // no canonical processing
        tty.c_oflag = 0;                // no remapping, no delays
        tty.c_cc[VMIN]  = 0;            // read doesn't block
        tty.c_cc[VTIME] = 5;            // 0.5 seconds read timeout

        tty.c_iflag &= ~(IXON | IXOFF | IXANY); // shut off xon/xoff ctrl

        tty.c_cflag |= (CLOCAL | CREAD);// ignore modem controls,
                                        // enable reading
        tty.c_cflag &= ~(PARENB | PARODD);      // shut off parity
        tty.c_cflag |= parity;
        tty.c_cflag &= ~CSTOPB;
        tty.c_cflag &= ~CRTSCTS;

        if (tcsetattr (fd, TCSANOW, &tty) != 0)
        {
                printf ("error %d from tcsetattr", errno);
                return -1;
        }
        return 0;
}

void set_blocking (int fd, int should_block)
{
        struct termios tty;
        memset (&tty, 0, sizeof tty);
        if (tcgetattr (fd, &tty) != 0)
        {
                printf ("error %d from tggetattr", errno);
                return;
        }

        tty.c_cc[VMIN]  = should_block ? 1 : 0;
        tty.c_cc[VTIME] = 5;            // 0.5 seconds read timeout

        if (tcsetattr (fd, TCSANOW, &tty) != 0)
                printf ("error %d setting term attributes", errno);
}

int main(void) {
	char *portname = "/dev/ttyMCC";
	
	int fd = open (portname, O_RDWR | O_NOCTTY | O_SYNC);
	if (fd < 0)
	{
			printf("error %d opening %s: %s", errno, portname, strerror (errno));
			return 0;
	}

	set_interface_attribs (fd, B115200, 0);  // set speed to 115,200 bps, 8n1 (no parity)
	set_blocking (fd, 0);                // set no blocking
	
	
	char numberX;
	char numberY;
	char nl;
	while(1){
			
		scanf("%c%c%c",&numberX,&numberY,&nl);
		write(fd, &numberX, 1);           		// send the number of the test_tube through the serial to the M4 processor
		write(fd, &numberY, 1); 
		sleep(1);					// wait 1 second
		
	}
	return 0;
}
ARM Cortex M4 CodeArduino
This is the code used to program the "ARM Cortex M4" real time co-processor, based on Arduino IDE.
#include <Servo.h> 

Servo myservo;                // create the object "servo" to control  
                              // the servo motor.
int pos = 0;                  // variable used to store the servo position.
int step_motorbig = 3;        // connect the "step" pin of the motor_big on pin 3 of the UDOO NEO.
int dir_motorbig = 2;         // connect the pin "direction" of the motor_big on pin 2 of the UDOO NEO.
int step_motorsmall = 13;     // connect the pin "step" of the motor_big on pin 13 of the UDOO NEO.
int dir_motorsmall = 12;      // connect the pin "direction" of the motor_big on pin 12 of the UDOO NEO.
int enable_steppers = 8 ;     // connect the pin "enable" of the two motors on pin 8 of the UDOO NEO.
int flag = 0;                 // create a flag to control the flow of the instructions.
int test_tube_numberX = 0;    // Contains the number of the test tube for the X axis (from 0 to 9).
int test_tube_numberY = 0;    // Contains the number of the test tube for the Y axis (from 0 to 9).
const int defaultX = 495;     // used to move the motor_big the necessary steps to arrive at the "zero" position on X axis.
const int defaultY = 440;     // used to move the motor_small the necessary steps to arrive at the "zero" position on Y axis.
const int StepX = 115;        // constant that shows the steps between 2 close holes for the motor_big.
const int StepY = 792;        // constant that shows the steps between 2 close holes for the motor_small.
int Change_deck = 0;          // variable that allows to change "Deck".

void LedGreenOn(){            // function that turns on the green LED.
  digitalWrite(9, HIGH);
}

void LedGreenOff(){           // function that turns off the green LED.
  digitalWrite(9, LOW);
}

void LedYellowOn(){           // function that turns on the yellow LED.
digitalWrite(10, HIGH);
}

void LedYellowblink2(){       // function that blinks the yellow LED 2 times.
  for (int i=0;i<2;i++)
  {
    digitalWrite(10, HIGH);
    delay(100);
    digitalWrite(10, LOW);
    delay(100);
  }
}

void LedYellowblink1(){       // function that blinks the yellow LED 1 time.
  for (int i=0;i<1;i++)
  {
    digitalWrite(10, HIGH);
    delay(100);
    digitalWrite(10, LOW);
    delay(100);
  }
}

void LedYellowOff(){          // function that turns off the yellow LED.
  digitalWrite(10, LOW);
}

void LedRedOn(){              // function that turns on the red LED.
  digitalWrite(11, HIGH);
}

void LedRedOff(){             // function that turns off the red LED.
  digitalWrite(11, LOW);
}

void Start(){                 // function that establishes the start procedure.
  LedGreenOff();
  LedRedOn();
  LedYellowOff();
  delay(45000);
  LedRedOff();
  LedGreenOn();
  digitalWrite(dir_motorsmall, LOW);
}

void StepperSmall_ReturnInitPos(){         // function that returns the motor_small 
                                           // at the "origin".
  delay(1000);
  LedGreenOff();
  LedRedOff();
  LedYellowOn();
  CloseServo();
  digitalWrite(enable_steppers, LOW);     // "enable" on, so the relative driver is on (pololu A4988). 
  if (digitalRead(4)!= HIGH){             // move the motor if the end stroke button is not pressed. 
    LedGreenOff();
    LedRedOff();
    LedYellowOn();
    if (dir_motorsmall == LOW){
      digitalWrite(dir_motorsmall, HIGH);  
    }
    else{
       digitalWrite(dir_motorsmall, LOW);
    }
    
    while (digitalRead(4) != HIGH){       // move the motor untill the end stroke button is pressed.
      
      digitalWrite(step_motorsmall, HIGH);   
      delayMicroseconds(650);        
      digitalWrite(step_motorsmall, LOW); 
      delayMicroseconds(650);
    }
  }
}

void StepperBig_ReturnInitPos(){          // function that returns the motor_small 
                                          // at the "origin".
  
  if (digitalRead(5)!= HIGH){             // move the motor if the end stroke button is not pressed.
    LedGreenOff();
    LedRedOff();
    LedYellowOn();
    digitalWrite(dir_motorbig, LOW);   
    
    while (digitalRead(5) != HIGH){       // move the motor untill the end stroke button is pressed.
      
      digitalWrite(step_motorbig, HIGH);   
      delayMicroseconds(900);        
      digitalWrite(step_motorbig, LOW); 
      delayMicroseconds(900);
          
    }
  }
  LedGreenOn();
  LedYellowOff();
  LedRedOff();
  digitalWrite(enable_steppers, HIGH);    
  flag = 0;
}

void OpenServo(){                         // function that rotate the servo motor to open the hole
                                          // that contains the test tube.
  delay(500);

  for(pos = 0; pos <= 100; pos += 50)     
  {                                       
    myservo.write(pos);                   // servo motor goes to the "pos" position.
    delay(15);                            
  }

}

void CloseServo(){                        // function that rotate the servo motor to close the hole
                                          // that contains the test tube.  
  for(pos = 100; pos>=0; pos-= 50)       
  {                                
    myservo.write(pos);                   // servo motor goes to the "pos" position.
    delay(15);                       
  } 
  
}

void MoveMotors(){                        // function that moves the two step motors to the position where the test tube  
                                          // will be released.
   
  digitalWrite(dir_motorbig, HIGH);       // set the "direction". 
  digitalWrite(dir_motorsmall, HIGH);     
  delay(2000);
  digitalWrite(enable_steppers, LOW);     
  LedGreenOff();
  LedRedOff();
  LedYellowOn();
  test_tube_numberY=test_tube_numberY+Change_deck;            
  if (test_tube_numberY>4 || test_tube_numberY<0 || test_tube_numberX>9 || test_tube_numberX<0 ){
    // check if the read code is right (0<X<9; 0<Y<4). If one of these values is not respected,
    // the test tube will be released in the "waste area".  
   
    for (int i = 0; i<200; i++){            // go to the "waste area".
      digitalWrite(step_motorbig, HIGH);   
      delayMicroseconds(900);        
      digitalWrite(step_motorbig, LOW);
      delayMicroseconds(900);
    }
    for (int i = 0; i<2500; i++){            // go to the "waste area".
      digitalWrite(step_motorsmall, HIGH);   
      delayMicroseconds(650);        
      digitalWrite(step_motorsmall, LOW); 
      delayMicroseconds(650);
    }
    
  }
  
  else{
  int A = defaultX+(test_tube_numberX*StepX);  // "A" contains the X position.
  for (int i = 0; i<A; i++){
    digitalWrite(step_motorbig, HIGH);   
    delayMicroseconds(900);        
    digitalWrite(step_motorbig, LOW);
    delayMicroseconds(900);
  }

  int B = defaultY+(test_tube_numberY*StepY);  // "B" contains the Y position.
  for (int i = 0; i<B; i++){
    digitalWrite(step_motorsmall, HIGH);   
    delayMicroseconds(650);        
    digitalWrite(step_motorsmall, LOW); 
    delayMicroseconds(650);
  }
  }
  digitalWrite(enable_steppers,HIGH);
  delay(500);
  OpenServo();
  delay(2000);
  digitalWrite(enable_steppers,LOW);
 
}


void ReadCode(){                                // function that read the two values insert from keyboard.
  if(Serial.available() >= 2){                  // check if the are 2 or more bytes in the receive buffer of the UART.             
     test_tube_numberY = (int ) Serial.read();  // read the first byte. 
     test_tube_numberX = (int ) Serial.read();  // read the second byte.
     test_tube_numberX -= 48;
     test_tube_numberY -= 48;
     delay(200);
     Serial.print(test_tube_numberY );
     Serial.print("  ");
     Serial.println(test_tube_numberX);
     while(Serial.available() > 0){
        Serial.read();
     }
      flag = 1; 
      
  }
  delay(50);
}

void Deck(){                                // function that choose the "Deck": "Deck1" for test tubes from 0 to 49,
                                            // "Deck2" for test tubes from 50 to 99.
     delay(500);
    if (digitalRead(7) == HIGH){
      if (Change_deck == 0){
      LedYellowblink2();
      Change_deck =- 5;
      LedYellowOff();
      }
      else {
      LedYellowblink1();
      Change_deck = 0;
      LedYellowOff();
      }
    }
    
}

void setup() {
  
  delay(20000);
  pinMode(9, OUTPUT);               // pin 9 for green LED.
  pinMode(11, OUTPUT);              // pin 11 for red LED.
  pinMode(10, OUTPUT);              // pin 10 for yellow LED.
  pinMode(5, INPUT);                // pin 5 for the end stroke button of the motor_big.
  pinMode(4, INPUT);                // pin 4 for the end stroke button of the motor_small.
  pinMode(7,INPUT);                 // pin 7 for the button that choose the "Deck".
  pinMode(step_motorbig, OUTPUT);
  pinMode(dir_motorbig, OUTPUT);  
  pinMode(step_motorsmall, OUTPUT);
  pinMode(dir_motorsmall, OUTPUT);
  pinMode(enable_steppers, OUTPUT);
  Start();
  myservo.attach(6);                 // connect the "servo" on pin 6.
  Serial.begin(115200);              // active the serial with baud rate of 115200 byte/s.
  delay(500);
  StepperSmall_ReturnInitPos();
  StepperBig_ReturnInitPos();
  
}

void loop() {
  
  while ( flag == 0 ){
    ReadCode();
    Deck();
  }
  
  MoveMotors();
  StepperSmall_ReturnInitPos();
  StepperBig_ReturnInitPos();

}

Credits

Img 3730
Andrea Fiaschi

I was born in 1993, I'm studying at University of Siena at the Faculty of Information Engineering and Computer science, specialized in Electronics.

Contact
Image201603040002
Federico Micheletti

I was born in 1993, I'm studying at the University of Study of Siena at the Faculty of Information Engineering and Computer science specialized in Electronics

Contact

Replications

Did you replicate this project? Share it!

Love this project? Think it could be improved? Tell us what you think!

Give feedback

Comments

Similar projects you might like

A powerful Maritime Instrument & Display Controller
Intermediate
  • 9,921
  • 55

Work in progress

A powerful Maritime Instrument & Display Controller, based on UDOO Neo, acting as a navigator, chart plotter, wireless NMEA multiplexer & ?

UDOO Ubuntu LTS Guide
Intermediate
  • 1,186
  • 23

Full instructions

Building a Ubuntu LTS configuration for the UDOO Quad

myva-Home (Voice controlled home automation)
Intermediate
  • 3,778
  • 40

Full instructions

My Voice Activated/Controlled Home, Using the Linkit Smart and an Android with easy to use examples and libraries

Home Energy Monitor
Intermediate
  • 2,450
  • 12

A low cost, high performance energy meter for my home.

SATA on UDOO
Intermediate
  • 1,748
  • 15

Full instructions

Experiences and benchmarks with SATA drives on the UDOO.

Offline Speech Processing
Intermediate
  • 2,630
  • 19

Protip

Create your very own hotwords like "Alexa," "Ok Google" and "Hey Cortana," and trigger events just by speaking - without the Internet.

Add projectSign up / Login