segunda-feira, 15 de abril de 2019

Medidor de pH - enviando os valores de pH e temperatura para planilha em Excel.

Olá pessoal, neste post veremos como enviar os dados de pH e temperatura para uma planilha em Excel utilizando o add-on PLX-DAQ.
Temos duas maneiras de enviar dados para o PC:

1) Através de cabo USB serial conectando o Arduino ao PC:

Basta conectar o cabo USB Serial do Arduino ao PC. Se o módulo Bluetooth estiver conectado à protoboard desconecte-o. Os valores podem ser visualizados pela Serial Monitor da IDE Arduino ou através de um software de comunicação serial como o Putty.  No Putty basta iniciar uma sessão Serial e informar a porta e a velocidade da porta COM utilizada pela USB Serial.




Para testar basta instalar o Putty e escolher a porta COM e a velocidade:





No caso a porta serial USB do Arduino ficou na COM4. Você pode verificar qual porta COM no Gerenciador de Dispositivos.

Há também a possibilidade no Putty de gravar os dados recebidos pela conexão serial em um arquivo. Basta ir em Session, Logging e escolher Printable Output e escolher qual o arquivo será criado para armazenar os dados coletados. Clique em Open para realizar a conexão.




 
2) Através do módulo Bluetooth.

Basta o módulo Bluetooth HC-06 estar conectado à protoboard e realizar o pareamento com o PC. O pin padrão do módulo é 1234. Uma vez pareado você pode utilizar o Putty e basta iniciar uma sessão Serial e informar a porta e a velocidade da porta COM utilizada pela USB Serial.
Para fazer a conexão do módulo bluetooth HC-06 com o PC é necessário fazer o pareamento.  

a) Uma vez instalado o dispositivo Bluetooth no PC clique no ícone Bluetooth:


 b) Clique na opção Adicionar um Dispositivo Bluetooth:



c) Será aberta uma janela de configurações. Escolha Adicionar Bluetooth ou outro dispositivo. Provavelmente o dispositivo será listado como Dispositivo Desconhecido. Clique nele e faça a conexão. Será solicitado o pin do dispositivo. Insira 1234.




d) Com o dispositivo Bluetooth pareado vá em Mais opções de Bluetooth para verificar qual porta COM está sendo utilizada para a conexão.




e) Vá na aba Portas COM. A porta COM a ser utilizada é a porta com direção de Saída (no meu caso aqui foi a COM4).








f) Utilize o Putty da mesma forma mostrada acima para testar a conexão Bluetooth e configurando a conexão para a porta COM da conexão Bluetooth (que no caso aqui foi a COM4).  Ao dar Open o terminal Putty deverá mostrar os dados coletados:









Uma vez sendo realizada a leitura dos dados pela serial ou Bluetooth devemos utilizar o add-on PLX-DAQ no Excel.
Siga as instruções de instalação do PLX-DAQ:

https://medium.com/@islamnegm/quick-start-to-simple-daq-system-using-plx-daq-excel-arduino-d2457773384b

Segue abaixo vídeo da coleta de dados sendo realizada através de Bluetooth:






Pessoal, assim finalizamos esse projeto. Quaisquer dúvidas entrem em contato.

Até a próxima!


Medidor de pH - código e testes com padrões

Olá pessoal, neste post detalharemos o código implementado no projeto. Deverão ser incluídas as seguintes bibliotecas:

- Biblioteca do display OLED:

https://drive.google.com/open?id=1MaeiU1YsQ3tkMxyT1USZct4PfxdLDRvt


- Biblioteca do sensor DHT11

https://drive.google.com/open?id=1THBI9MKPokXgnx5_Jnd9vCjXYL5lf3oM

- Biblioteca FloattoString.

https://drive.google.com/open?id=1aC8H2M-vkNCZYfp745po6FRstfCYaEb-



Segue código:

#include <Arduino.h>
#include <U8g2lib.h> // Biblioteca do display OLED
#include <SPI.h>
#include <Wire.h>
#include <FloatToString.h> // Biblioteca para converter float para string

#include <dht11.h> //Biblioteca do sensor DHT11

U8G2_SSD1306_128X32_UNIVISION_F_HW_I2C u8g2(U8G2_R0); //Inicializa variável u8g2 para manipular display OLED.

float calibration = 0.25; //alterar o valor para calibrar quando não conseguir no potenciômetro do sensor pH.
const int analogInPin = A0; //pino para leitura do pH.
int sensorValue = 0;
unsigned long int avgValue;
float b;
int buf[100],temp; //matriz buf com 100 elementos para armazenar os valores de tensão lidos.
char buffer[25]; // buffer utilizado para converter float para string
dht11 sensor; //objeto do tipo dht11

void setup() {
    Serial.begin(9600);
    Serial.println("CLEARDATA");  //CLEARDATA para utilização no PLX-DAQ
    Serial.println("LABEL,Hora,Temp,pH"); //Cabeçalho dos dados para utilizar no PLX-DAQ
    u8g2.begin();  //inicializa display OLED

}

void loop() {
    

    int chk = sensor.read(2); // sensor faz a leitura no pino D2
       
    //Loop para fazer a leitura de 100 valores de tensão no pino A0
    for(int i=0;i<100;i++)
    {
        buf[i]=analogRead(analogInPin);
        delay(10);

    }
    

    //Ordena os valores de tensão
    for(int i=0;i<100;i++)
    {
        for(int j=i+1;j<100;j++)
        {
            if(buf[i]>buf[j])
            {
                temp=buf[i];
                buf[i]=buf[j];
                buf[j]=temp;
            }
        }
    }
   
    avgValue=0;


    //Considera 96 valores e calcula a média da amostra
    for(int i=2;i<97;i++)
          avgValue+=buf[i];



    //Calcula o valor médio de tensão do sensor pH  

    float pHVol=(float)avgValue*4.94/1024/96;

    //Converte para string o valor float do phVol e deixa com somente dois dígitos

    String spHVol = floatToString(buffer, pHVol, 2);
    

    //Converte a string spHVol para float novamente mas agora somente com dois dígitos
    float fpHVol = spHVol.toFloat();
   

    //De posse do valor médio de tensão calcula-se o valor de pH acrescentando a calibração
    float phValue = -5.70 * fpHVol + 21.34 + calibration;
    

    if (phValue < 0){
        phValue = 0; 
    }




    // A série de prints abaixo vai escrever na Serial os valores separados por vírgula do pH e da temperatura para utilização no PLX-DAQ
    Serial.print("DATA,TIME,");
    Serial.print((float)sensor.temperature,0);
    Serial.print(",");
    Serial.println(phValue);
   
    // Mostra os valores no display OLED
    u8g2.clearBuffer();         // clear the internal memory
    u8g2.setFont(u8g2_font_logisoso24_tr);  // choose a suitable font at https://github.com/olikraus/u8g2/wiki/fntlistall
    u8g2.setCursor(6,30); // write something to the internal memory
    u8g2.print("pH:"); // write something to the internal memory
    u8g2.setCursor(60,30); // write something to the internal memory
    u8g2.print(phValue,2); // write something to the internal memory
    u8g2.sendBuffer();
    delay(2000);
    u8g2.clearBuffer();         // clear the internal memory
    u8g2.setFont(u8g2_font_logisoso18_tr);  // choose a suitable font at https://github.com/olikraus/u8g2/wiki/fntlistall
    u8g2.setCursor(6,30); // write something to the internal memory
    u8g2.print("T:"); // write something to the internal memory
    u8g2.setCursor(50,30); // write something to the internal memory
    u8g2.print((float)sensor.temperature,0); // write something to the internal memory
    u8g2.setCursor(75,30); // write something to the internal memory
    u8g2.print("*C"); // write something to the internal memory
    u8g2.sendBuffer();v
   
     delay(1000);
}


Há alguns detalhes no código que precisam ficar atentos. O valor de tensão de alimentação do sensor deve ser medido com um multímetro e ser utilizado no cálculo da variável phVol (tensão do sensor que será utilizado no cálculo do pH). No caso do código acima o valor obtido foi 4.94 no VCC e GND do sensor pH.

Uma vez feito o upload do código vamos testar as leituras em soluções padrão de pH 7 inicialmente, calibrando o sensor através do potenciômetro mais próximo do conector BNC do módulo sensor pH ou através do código pela variável calibration. Se o potênciômetro não conseguir chegar no valor de pH 7, por exemplo chegando no valor 6.88 e não é mais possível ajustar pelo potenciômetro basta colocar o valor de 0.12 na variável calibration no código para ajustar o ph 7.
Em seguida, tomando os cuidados necessários para não contaminar os padrões (lavando o eletrodo com água destilada e enxugando a cada troca de padrão) fazer o teste com ph 4. A leitura não deve ficar com mais de 0.5 pH de diferença para mais ou para menos. Se houver uma diferença muito grande o problema pode estar no eletrodo. Em testes de laboratório verificamos que determinados eletrodos não respondiam em algumas soluções ácidas..



A grande vantagem de utilizarmos Arduino é que podemos automatizar alguns testes de laboratório deixando a cargo do Arduino enviar os dados para um PC ou até mesmo um smartphone e depois visualizar esses dados de forma gráfica.
No próximo post veremos como coletar os dados enviados pela Serial do Arduino ou através de Bluetooth para uma planilha utilizando um add-on do Excel chamado PLX-DAQ.
Até a próxima!

Medidor de pH - conexão dos componentes e detalhes de implementação

pH significa “potencial hidrogeniônico”, uma escala utilizada para medir acidez, neutralidade ou alcalinidade de uma determinada solução. Tamanha é sua importância, que a determinação do pH é realizada em laboratórios de controle de qualidade em diversas indústrias, como a indústria química, de alimentos, bebidas, de cosméticos, farmacêutica, análises clínicas e até no controle da preservação do meio ambiente.

Neste post veremos um novo projeto desenvolvido no meu local de trabalho (campus da UNESP Sorocaba - Instituto de Ciências e Tecnologia de Sorocaba) para atender uma demanda de construção de um medidor de pH utilizando Arduino, com base neste projeto:

https://pubs.acs.org/doi/abs/10.1021/acs.jchemed.7b00479

Fizemos adaptações no projeto para utilizar o módulo de leitura pH PH-4502C e o eletrodo que vem junto com ele :

https://www.usinainfo.com.br/outros-sensores-arduino/sensor-de-ph-arduino-modulo-de-leitura-5316.html




Os demais componentes utilizados são:

- Arduino Nano



- Sensor de temperatura DHT11




- Display OLED 0.91




- Módulo Bluetooth HC-06:


- Protoboard 830 pontos:




- Conector P4 fêmea com borne para fonte de alimentação externa:





- Fonte de alimentação externa 9V:





- Jumpers Dupont macho-macho e macho-fêmea:





A figura abaixo mostra os componentes conectados:



Detalhes da implementação:

1) Alimentação externa: para fornecer tensão constante próxima dos 5V necessários para o sensor foi utilizada fonte de alimentação externa de 9V, ligando o positivo do conector P4 na entrada Vin do Arduino e o negativo no pino GND. O interessante é que também é possível conectar uma bateria de 9V usando um jack apropriado. É importante salientar que não é recomendado utilizar alimentação pela USB do Arduino por apresentar geralmente valores bem abaixo dos 5V necessários.
2) Foi utilizado um display OLED 0.91 para visualizar os valores de pH e temperatura. A alimentação do display é de 3.3V e o VCC do display é conectado ao pino 3V3 do Arduino.
3) DHT11: ligar normalmente o sensor DHT11 (não esquecendo do resistor de 10K entre o pino de DATA e o VCC). O pino de DATA está conectado na porta D2 do Arduino.
4) Módulo Bluetooth: o módulo Bluetooth está utilizando os pinos TX e RX do Arduino. Optamos por utilizar os mesmos pinos da comunicação serial padrão do Arduino para simplificar. Para fazer o upload do código através do cabo USB serial do Arduino basta desplugar o módulo da protoboard.
5) Sensor pH: o sensor é alimentado com 5V, a leitura de pH se dá pelo pino Po do módulo pH e este é conectado no pino A0 do Arduino. Os dois pinos de terra (alimentação e do eletrodo) são ligados no  GND do Arduino.

A imagem abaixo mostra o projeto como ficou:

 


No próximo post veremos o código do projeto e seus detalhes. Até a próxima!

segunda-feira, 6 de agosto de 2018

Novo projeto: levitador acústico

Olá pessoal,

Depois de muito tempo sem postar vamos falar agora de um novo projeto que me despertou bastante interesse em implementá-lo embora não fosse um projeto de aplicação prática para o meu dia a dia. Ouvi falar do levitador acústico no Arduino Day 2018 e me interessou bastante e li o instructables do projeto do Asier Marzo. Vamos lá.

Como funciona a levitação acústica:

http://www.oarquivo.com.br/variedades/ciencia-e-tecnologia/4306-levita%C3%A7%C3%A3o-ac%C3%BAstica-2.html



Projeto Levitador Acústico do Instructables:

https://www.instructables.com/id/Acoustic-Levitator/


Vídeo do projeto:



Vídeo por Physics Girl explicando a física por trás do levitador acústico:

https://www.youtube.com/watch?time_continue=9&v=ABjRnSYw-4k


Como o projeto é bem detalhado no instructables os próximos posts serão sobre dicas de como implementar o projeto. Até mais!

quarta-feira, 4 de outubro de 2017

Agitador magnético com controle de velocidade com Arduino

Olá pessoal,

No post anterior fizemos um agitador magnético caseiro utilizando um potênciômetro para controlar a velocidade do agitador e está funcionando muito bem. Neste post faremos um controle de velocidade através de dois botões: um para aumentar a velocidade e outro para diminuir a velocidade em até 10 velocidades diferentes e um display OLED que vai informar a velocidade do agitador.

Componentes utilizados:

- 1 TIP122
- 1 Display OLED 0.96" I2C
- 2 push-button
- 1 Diodo 1N4001

O funcionamento do circuito é simples: escreve-se na saída PWM da porta digital 9 um determinado valor e nessa saída está ligado à base do TIP 122, esse transistor de potência está no circuito para controlar a corrente que é mais alta no motor, a partir de uma corrente baixa proporcionada pela saída PWM do Arduino, funcionando como um amplificador.
 Usa-se o TIPpois o motor requer uma corrente mais alta que a disponível no Arduino, e alimentá-lo diretamente com o microcontrolador danifica o último, portanto sua alimentação é feita por uma fonte de 12V. O diodo 1N4001 foi colocado como uma proteção para a contra-corrente que o motor pode induzir.
Pressionando-se os botões para aumentar ou diminuir a velocidade altera-se o valor de escrita na porta 9. Quanto mais alto o valor de escrita maior a velocidade.
Note que os terras da fonte e do Arduino estão interligados.

Segue o código utilizado:

#include "U8glib.h"
#include <stdlib.h>


int btnMais = 4;
int btnMenos = 3;
int velocidade = 0;
int intervalo = 22;
int rotacaomin = 57;
int rotacaomax = 255;
int rotacaoatual;
int btnMaisState;
int btnMenosState;
char tempvelocidade[2];

U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_NO_ACK);  // Display which does not send AC



void setup() {
 
      pinMode(9,OUTPUT);
      pinMode(btnMais,INPUT);
      pinMode(btnMenos,INPUT);
      Serial.begin(9600);
      if ( u8g.getMode() == U8G_MODE_R3G3B2 ) {
          u8g.setColorIndex(255);     // white
      }
      else if ( u8g.getMode() == U8G_MODE_GRAY2BIT ) {
          u8g.setColorIndex(3);         // max intensity
      }
      else if ( u8g.getMode() == U8G_MODE_BW ) {
          u8g.setColorIndex(1);         // pixel on
      }
      else if ( u8g.getMode() == U8G_MODE_HICOLOR ) {
          u8g.setHiColorByRGB(255,255,255);
  }
 }


void loop() {
    btnMaisState = digitalRead(btnMais);
    btnMenosState = digitalRead(btnMenos);
   
    if ((velocidade >=0 ) && (velocidade <= 10)) {
      if ((btnMaisState == HIGH) && (velocidade < 10)) {
         velocidade = velocidade + 1;
      }
   
      if ((btnMenosState == HIGH) && (velocidade > 0)) {
         velocidade = velocidade - 1;
      } 
     
      switch (velocidade) {
        case 0:
            //Para o ventilador
            analogWrite(9,0);
            rotacaoatual = 0;
            break;
        case 1:
            analogWrite(9,rotacaomin);
            rotacaoatual = rotacaomin;
            break;
        case 2:
            analogWrite(9,rotacaomin+(1*intervalo));
            rotacaoatual = rotacaomin+(1*intervalo);
            break;
        case 3:
            analogWrite(9,rotacaomin+(2*intervalo));
            rotacaoatual = rotacaomin+(2*intervalo);
            break;
        case 4:
            analogWrite(9,rotacaomin+(3*intervalo));
            rotacaoatual = rotacaomin+(3*intervalo);
            break;
        case 5:
            analogWrite(9,rotacaomin+(4*intervalo));
            rotacaoatual = rotacaomin+(4*intervalo);
            break;
        case 6:
            analogWrite(9,rotacaomin+(5*intervalo));
            rotacaoatual = rotacaomin+(5*intervalo);
            break;
        case 7:
            analogWrite(9,rotacaomin+(6*intervalo));
            rotacaoatual = rotacaomin+(6*intervalo);
            break;
        case 8:
            analogWrite(9,rotacaomin+(7*intervalo));
            rotacaoatual = rotacaomin+(7*intervalo);
            break;
        case 9:
            analogWrite(9,rotacaomax+(8*intervalo));
            rotacaoatual = rotacaomin+(8*intervalo);
            break;
        case 10:
            analogWrite(9,rotacaomax+(9*intervalo));
            rotacaoatual = rotacaomin+(9*intervalo);
            break;
   
       }  
    }
    itoa(velocidade,tempvelocidade,10);
    u8g.firstPage(); 
    do
    {
          //Comandos graficos para o display devem ser colocados aqui
          //Seleciona a fonte de texto
          u8g.setFont(u8g_font_8x13B);
          u8g.drawStr( 24, 15, "VELOCIDADE");
          u8g.setFont(u8g_font_fub30);
          if (velocidade == 10) {
              u8g.drawStr(41,57,tempvelocidade);
          }
          else
          { 
          u8g.drawStr(50,57,tempvelocidade);
          }
          u8g.drawRFrame(0, 18, 128, 46, 4);


    } while( u8g.nextPage() );
  
    delay(500);
 
}

Segue abaixo vídeo mostrando o funcionamento:




 Pessoal, é isso aí! Quaisquer dúvidas entrem em contato!







sexta-feira, 29 de setembro de 2017

Novo projeto: agitador magnético com controle de velocidade

Olá pessoal!

Neste post vamos iniciar um novo projeto que consiste de um agitador magnético caseiro, feito de materiais facilmente encontrados como sucatas eletrônicas e que, no final de contas, possibilitam a implementação com baixo custo. Primeiramente vamos implementar sem nenhum tipo de controle com Arduino, usando somente um potenciômetro para controlar a velocidade de um ventilador. Vamos lá!

Os materiais que utilizei foram estes:

1)  Quadro Tigre para acomodar o cooler.





















2) Cooler de PC 12V: o cooler foi retirado de uma fonte de computador e fixado na tampa do quadro Tigre.

















3) Imã de neodímio: nesta mesma tampa do outro lado ficará uma abertura onde serão fixados os dois imãs. Foi utilizada cola quente.

















4) Potenciômetro de 5K: é feita uma pequena abertura com uma furadeira para acomodar o potenciômetro na lateral da caixa:
















5) Protoboard pequena: vide imagem acima.


6) Fonte de 12V 1A: é feita uma pequena abertura na lateral da caixa para a passagem do cabo da fonte de 12V. Coloquei dois conectores de protoboard nos dois fios da fonte.

















 
7) Capa de CD (acrílico): pegar uma capa de CD em acrílico e desmontar. pegar a parte com parte lisa e colar com cola quente na caixa para que fique logo acima dos imãs sem tocá-los.

















Ficará assim:


















7) Peixinho para agitador magnético: o peixinho é um imã ou mesmo um pedaço de metal que fará o movimento no líquido. Você pode comprar o peixinho ou fazer o peixinho utilizando a parte plástica da caneta esferográfica (tira a carga da caneta e corta-se o tubo plástico do tamanho que se quer o peixinho) e duas  tampas de tubo da esferográfica (outra extremidade da caneta). Basta inserir um parafuso, pedaço de arame grosso ou mesmo um outro imã bem pequeno no tubo cortado e fechar com duas tampas de tubo (não é a tampa da caneta mas sim a do tubo, conforme imagem abaixo).


Peixinho magnético


















A montagem interna ficou assim:

















E o resultado final depois de fechada a tampa:

















O vídeo final mostrando o funcionamento:




No próximo post colocaremos um Arduino para controlar a velocidade através de dois botões. Teremos 10 velocidades diferentes e poderemos aumentar ou diminuir a velocidade usando esses dois botões.


sexta-feira, 5 de agosto de 2016

Tape changer - códigos de implementação dos comandos do trocador de fitas

Olá pessoal,

Neste post veremos a implementação dos comandos do trocador de fitas. Através de comandos recebidos pela serial o Arduino aciona os motores e o servo para fazer os movimentos.

// Programa : Tape changer - garra e motores de passo
// Autor : Fernando Asashi Nitatori 
#include <Servo.h>  // Biblioteca para acionamento do servo
#include <AccelStepper.h> //Biblioteca para os motores de passo

Servo myservo;  // Cria um objeto do tipo Servo para controlar um servo chamado myservo

int pos = 0;    // variavel para armazenar a posicao do servo
int position;
int positioncenter = 84; // variavel para setar a posicao central do servo

int velocidade_motor_1 = 600; //velocidade do motor de passo 1
int velocidade_motor_2 = 600; //velocidade do motor de passo 1
int aceleracao_motor_1 = 80; //aceleracao do motor de passo 1
int aceleracao_motor_2 = 80; //aceleracao do motor de passo 1
int sentido_horario_motor_1 = 0;
int sentido_antihorario_motor_1 = 0;
int sentido_horario_motor_2 = 0;
int sentido_antihorario_motor_2 = 0;
int chave1;
int chave2;
int chave3;
int pino_endstop1 = 9;
int pino_endstop2 = 10;
int pino_endstop3 = 11;
int posicao = 0;
int posicao2 = 0;
int posicao1_motor1 = 8000;
int posicao2_motor1 = 16000;
int posicao3_motor1 = 24000;
int posicao1_motor2 = 2500;
int posicao2_motor2 = 10000;
int posicao3_motor2 = 22000;

char ultcmdservo = 'm';

char comando;

// Definicao pino ENABLE
int pino_enable = 8;

// Definicao pinos STEP e DIR
AccelStepper motor1(1,2,5);
AccelStepper motor2(1,4,7);


void setup() 
{
  Serial.begin(9600);
  pinMode(pino_enable, OUTPUT);

  pinMode(pino_endstop1, INPUT);
  pinMode(pino_endstop2, INPUT);
  pinMode(pino_endstop3, INPUT);
  digitalWrite(pino_endstop1, HIGH);
  digitalWrite(pino_endstop2, HIGH);
  digitalWrite(pino_endstop3, HIGH);

  // Configuracoes iniciais motor de passo
  motor1.setEnablePin(pino_enable);
  motor1.setMaxSpeed(velocidade_motor_1);
  motor1.setSpeed(velocidade_motor_1);
  motor1.setAcceleration(aceleracao_motor_1);
 
  // Configuracoes iniciais motor de passo
  motor2.setEnablePin(pino_enable);
  motor2.setMaxSpeed(velocidade_motor_2);
  motor2.setSpeed(velocidade_motor_2);
  motor2.setAcceleration(aceleracao_motor_2);

  sentido_horario_motor_1 = 0;
  sentido_antihorario_motor_1 = 0;
  sentido_horario_motor_2 = 0;
  sentido_antihorario_motor_2 = 0;
 
 
  ligaservo();
  myservo.write(positioncenter);
  Serial.println("Digite l, m ou r para movimentar o servo e clique em ENVIAR...");
  Serial.println("Digite c para parar o motor 1...");
  Serial.println("Digite f para parar o motor 2...");

  Serial.println("Digite 0 para girar o motor 1 para esquerda.");
  Serial.println("Digite 1 para girar o motor 1 para a posicao 1.");
  Serial.println("Digite 2 para girar o motor 1 para a posicao 2.");

  Serial.println("Digite 3 para girar o motor 1 para a posicao 3.");
  Serial.println("Digite 5 para girar o motor 2 para esquerda.");

  Serial.println("Digite 6 para girar o motor 2 para a posicao 6.");
  Serial.println("Digite 7 para girar o motor 2 para a posicao 7.");
 
  //Serial.println("Digite 8 para girar o motor 2 para a posicao 8.");

}

void ligaservo() {
     myservo.attach(19,500,2700);  // attaches the servo on pin 19 to the servo object
}

void desligaservo() {
     myservo.detach();  //desliga o servo
}

/*
void movezero() {
      posicao = 0;
      moveposicao0motor1();
}
*/
void moveposicao0motor1() {
       digitalWrite(pino_enable, LOW);
       sentido_horario_motor_1 = 0;
       sentido_antihorario_motor_1 = 1;
}

void moveposicao0motor2() {
       digitalWrite(pino_enable, LOW);
       sentido_horario_motor_2 = 1;
       sentido_antihorario_motor_2 = 0;
}

void moveposicao1motor2() {
       digitalWrite(pino_enable, LOW);
       sentido_horario_motor_2 = 0;
       sentido_antihorario_motor_2 = 1;
       posicao2 = 1;
}

void moveposicao2motor2() {
       digitalWrite(pino_enable, LOW);
       sentido_horario_motor_2 = 0;
       sentido_antihorario_motor_2 = 1;
       posicao2 = 2;
}

void moveposicao3motor2() {
       digitalWrite(pino_enable, LOW);
       sentido_horario_motor_2 = 0;
       sentido_antihorario_motor_2 = 1;
       posicao2 = 3;
}

void moveposicao1motor1() {
       digitalWrite(pino_enable, LOW);
       sentido_horario_motor_1 = 1;
       sentido_antihorario_motor_1 = 0;
       posicao = 1;
}

void moveposicao2motor1() {
       digitalWrite(pino_enable, LOW);
       sentido_horario_motor_1 = 1;
       sentido_antihorario_motor_1 = 0;
       posicao = 2;
}

void moveposicao3motor1() {
       digitalWrite(pino_enable, LOW);
       sentido_horario_motor_1 = 1;
       sentido_antihorario_motor_1 = 0;
       posicao = 3;
}

void ligamotor1horario() {
       digitalWrite(pino_enable, LOW);
       sentido_horario_motor_1 = 1;
       sentido_antihorario_motor_1 = 0;

}

void ligamotor1antihorario() {
        digitalWrite(pino_enable, LOW);
        sentido_horario_motor_1 = 0;
        sentido_antihorario_motor_1 = 1;

}

void ligamotor2horario () {
        digitalWrite(pino_enable, LOW);
        sentido_horario_motor_2 = 1;
        sentido_antihorario_motor_2 = 0;
       
}

void ligamotor2antihorario() {
        digitalWrite(pino_enable, LOW);
        sentido_horario_motor_2 = 0;
        sentido_antihorario_motor_2 = 1;
  //      puxa_horario_motor_2 = 0;
  //      puxa_antihorario_motor_2 = 0;
      

}



void loop()
{
 
  // Aguarda os caracteres na serial
  if (Serial.available() > 0)
  {
      comando = (char) Serial.read();
   
      if (comando == 'c')
      {
        Serial.println("Letra c recebido - Parando motor 1...");
        sentido_horario_motor_1 = 0;
        sentido_antihorario_motor_1 = 0;
        motor1.stop();
        motor1.runToPosition();
        motor1.setCurrentPosition(0);
        digitalWrite(pino_enable, HIGH);
      }
     
      if (comando == 'f')
      {
        Serial.println("Letra f recebido - Parando motor 2...");
        sentido_horario_motor_2 = 0;
        sentido_antihorario_motor_2 = 0;
        motor2.stop();
        motor2.runToPosition();
        motor2.setCurrentPosition(0);
        digitalWrite(pino_enable, HIGH);
      }
     
      if (comando == 'l') {
         ligaservo();
         if (ultcmdservo == 'r') {
             Serial.println("Nao digitar comando r aqui. Va para o centro com m e depois va para direita com r");
         }
         else
         {
             for(pos = positioncenter; pos<=162; pos += 1) 
             {               
                    myservo.write(pos);              // tell servo to go to position in variable 'pos'
                    delay(50);
             }
         }
         ultcmdservo = 'l';
         desligaservo();
      }

      if (comando == 'm') {
           ligaservo();
           position = myservo.read();
           //Serial.println(position);
           if (position >= positioncenter) {
               for(pos = position; pos>=positioncenter; pos -= 1)  // goes from 0 degrees to 180 degrees
                {
                        myservo.write(pos);              // tell servo to go to position in variable 'pos'
                        delay(50);                       // waits 15ms for the servo to reach the position
                }
                 
           }        
           else
           {
              for(pos = position; pos<=positioncenter; pos += 1)  // goes from 0 degrees to 180 degrees
               {                                  // in steps of 1 degree
               
                      myservo.write(pos);              // tell servo to go to position in variable 'pos'
                      delay(50);                       // waits 15ms for the servo to reach the position
               }
           }
           ultcmdservo = 'm';
           desligaservo();
      }
 
      if (comando == 'r') {
         ligaservo();
         if (ultcmdservo == 'l') {
             Serial.println("Nao digitar comando l aqui. Va para o centro com m e depois va para direita com l");
         }
         else
         {
             for(pos = positioncenter; pos>=5; pos-=1)  { 
                  myservo.write(pos);              // movimenta o servo ate a posicao 
                  delay(50);                       // espera 50ms para o servo atingir a posicao
              }
         }
         ultcmdservo = 'r';
         desligaservo();   
      }    
     
      if (comando == '0') {
          moveposicao0motor1();
      }

     
      if (comando == '1') {
          moveposicao1motor1();
      }

      if (comando == '2') {
          moveposicao2motor1();
      }

      if (comando == '3') {
          moveposicao3motor1();
      }

      if (comando == '5') {
          moveposicao0motor2();
      }
     
      if (comando == '6') {
          moveposicao1motor2();
      }
     
      if (comando == '7') {
          moveposicao2motor2();
      }
     
      if (comando == '8') {
          moveposicao3motor2();
      }
  }

  chave1 = digitalRead(pino_endstop1);
  chave2 = digitalRead(pino_endstop2);
  chave3 = digitalRead(pino_endstop3);
      
  // Move o motor1 no sentido horario ate a posicao desejada
  if (sentido_horario_motor_1 == 1){
          if (posicao == 1) {
              motor1.moveTo(posicao1_motor1);
              motor1.run();
          }
          if (posicao == 2) {
              motor1.moveTo(posicao2_motor1);
              motor1.run();
          }
          if (posicao == 3) {
              motor1.moveTo(posicao3_motor1);
              motor1.run();
          }
         
  }
 
  // Move o motor1 no sentido anti-horario ate a posicao desejada
  if (sentido_antihorario_motor_1 == 1){
        if (posicao == 0) {// se posicao for 0 move ate encontrar chave fim de curso
           if (chave1 == 0) {
              Serial.println("Fim de curso - Parando motor 1...");
              sentido_horario_motor_1 = 0;
              sentido_antihorario_motor_1 = 0;
              motor1.stop();
              motor1.runToPosition();
//              motor1.setCurrentPosition(0);
              digitalWrite(pino_enable, HIGH);
            }
            else
            {
                motor1.move(-20000);
                motor1.run();
            }
       }
           motor1.moveTo(0);
           motor1.run();
  }
 
 
  // Move o motor2 no sentido horario ate a posicao desejada
  if (sentido_horario_motor_2 == 1){
      if (posicao2 == 0) {
          if (chave2 == 0) {
            Serial.println("Fim de curso 2 - Parando motor 2...");
            sentido_horario_motor_2 = 0;
            sentido_antihorario_motor_2 = 0;
            motor2.stop();
            motor2.runToPosition();
            digitalWrite(pino_enable, HIGH);
          }
          else
          {
          motor2.move(-19000);
          motor2.run();
          }
      }

          motor2.moveTo(0);
          motor2.run();

  }
 
  // Move o motor2 no sentido anti-horario ate a posicao desejada
  if (sentido_antihorario_motor_2 == 1) {
       if (posicao2 == 1) {
              motor2.moveTo(posicao1_motor2);
              motor2.run();
          }
      
       if (posicao2 == 2) {
              motor2.moveTo(posicao2_motor2);
              motor2.run();
          }
      
       if (posicao2 == 3) {
              motor2.moveTo(posicao3_motor2);
              motor2.run();
          }
   } 

}





O código acima  é para a implementação do movimento da garra e servo. Segue abaixo código para o motor DC:

 //Programa: Tape changer - abre e fecha a garra

#include <AFMotor.h>

AF_DCMotor motor(1);

char comando;

void abregarra() {
            uint8_t i;
            motor.run(BACKWARD);

            for (i=0; i<128; i++) {
                motor.setSpeed(i);
                delay(10);
            }
            delay(3000);
            motor.run(RELEASE);
}

void fechagarra() {
            uint8_t i;
          
            motor.run(FORWARD);
 
            for (i=0; i<255; i++) {
                motor.setSpeed(i);
                delay(10);
             }

             delay(2000);  
 
}

void setup () {
      Serial.begin(9600);
 
}

void loop () {
      if (Serial.available() > 0)
      {
          comando = (char) Serial.read();
          
          if (comando == 'g')
          {
              Serial.println("Abrindo garra");
              abregarra();
          }
     
          if (comando == 'h')
          {
              Serial.println("Fechando garra");
              fechagarra();
          }
      }
}

 O script retirafita.sh é um script que roda em shell Linux ou FreeBSD. Segue abaixo script completo com os comandos para retirar a fita do drive e colocá-la no compartimento:

#Script retira.sh
echo "Abre a garra..."
echo 'g' > /dev/tty.usbmodem1421
sleep 5s
echo "Fecha a garra..."
echo 'h' > /dev/tty.usbmodem1421
sleep 5s
echo "Movimenta a garra ate a posicao 8..."
echo '8' > /dev/tty.usbmodem1411
sleep 45s
echo "Vira para a direita..."
echo 'r' > /dev/tty.usbmodem1411
sleep 5s
echo "Movimenta a garra ate a posicao 5..."
echo '5' > /dev/tty.usbmodem1411
sleep 45s
echo "Abre a garra..."
echo 'g' > /dev/tty.usbmodem1421
sleep 5s
echo "Movimenta a garra ate a posicao 7..."
echo '7' > /dev/tty.usbmodem1411
sleep 22s
echo "Fecha a garra..."
echo 'h' > /dev/tty.usbmodem1421
sleep 5s
echo "Movimenta a garra ate a posicao 5..."
echo '5' > /dev/tty.usbmodem1411
sleep 27s
echo "Movimenta a garra ate a posicao 6..."
echo '6' > /dev/tty.usbmodem1411
sleep 10s
echo "Vai para o centro..."
echo 'm' > /dev/tty.usbmodem1411
sleep 5s
echo "Abre a garra..."
echo 'g' > /dev/tty.usbmodem1421
sleep 5s
echo "Movimenta a garra ate a posicao 5..."
echo '5' > /dev/tty.usbmodem1411
sleep 5s


Quaisquer dúvidas sobre os códigos entrem em contato,

Até mais pessoal,