sábado, 11 de agosto de 2012

Motorizando patinete infantil




Uma postagem anterior mostrava a motorização de um carrinho de criança usando um motor de vidro elétrico, um ESC com relés tendo como "celebro" um PICAXE 08M, veja aqui. Desta vez o alvo é uma patinete da Barbie, brinquedo de minha filha de cinco anos. O motor usado, bem como as adaptações feitas no conjunto motor redutor são as mesmas do carrinho. Como não há necessidade de ré os relés foram dispensados. A placa, usada para controlar a velocidade tem basicamente o Picaxe, um mosfet e um regulador de voltagem.

Adaptação mecânica

Algumas modificações foram feitas. O eixo traseiro foi substituído por uma barra roscada de 3/8”. Essa barra passo por dentro da engrenagem centrar do conjunto motor redutor. Assim como no carrinho a barra é presa no motor e nas rodas com uso de porca e contra porca. Dois pequenos pedaços de tubo de PVC 1/2" foram usados para afastar as rodas da patinete. Foi feito um furo na parte traseira para que fosse possível abrigar a placa de controle no interior da patinete e prender o motor com auxilio de uma abraçadeira feita de chapa de alumínio.

Parte eletroeletrônica

Ao lado é possível ver o diagrama do circuito usado para controlar a velocidade de rotação o motor. O acelerador está representado como um potenciometro mas, na verdade, não sei o que ele realmente tem dentro. Consegui usa-ló depois de alguns testes. Dois pinos do PICAXE 08M são usados, uma como entrada analógica para o acelerador e outro como saída PWM para o mosfet, que aciona o motor. Um acoplador ótico é usado entre o picaxe e o mosfet. A placa ainda possui um regulador de voltagem 7805 responsável pela alimentação do PICAXE (5V).

O programa

O programa é extremamente simples Nele o picaxe lê o valor do acelerador através de uma entrada analógica. Vale ressaltar que o acelerador usado aqui quando na posição de descano envia um valor maior que zero. Depois de alguns testes percebeu-se que 250 seria o valor suficiente para garantir que a patinete permanecesse parada quando não houvesse acionamento do acelerador. Quando o valor é menor que 250 o programa mantém o motor parado. Quando o valor lido é maior que 250 esse valor e usado para gerar o PWM que será aplicado ao motor através do pino 2.


symbol acel_value = w1

symbol motor_pin =  2

main: 'loop principal

' le o valor do acelerador no pino 4 e armazena
' em acel_value (w1)

READADC10 4, acel_value  

'se o valor for menor que 250 mantem o motor parado

if acel_value < 250  then 

pwmout motor_pin,255,0

'se o valor for maior que 250 aplica-o (PWM) ao motor

else

pwmout motor_pin,255,acel_value

endif

goto main 'fim do loop principal

terça-feira, 7 de agosto de 2012

Arduino LDR matriz



Dada a impossibilidade de usar uma câmera como sensor no arduino, pensei na possibilidade de construir uma espécie de CCD de muito baixa resolução, utilizando LDRs. Pesquisando na internet encontre este site com um excelente trabalho na criação de uma mesa com 64x64 LDRs. Decidi então construir uma pequena matriz, 3x4, para testes.
 

O LDR (Light Dependent Resistor) como o próprio nome sugere é um resistor que tem sua resistência variada em função da luz que incide sobre ele. Quanto maior a luz menor a resistência. Se ligado a uma entrada analógica do arduino tem-se um valor proporcional à luz que incide sobre o LDR teoricamente entre 0 e 1024.

A ideia principal é ler através da porta analógica do Arduino cada LDR e enviar esses valores ao processig que, pro sua vez usa estes valores para determinas o tom de cinza de um retângulo formado por doze quadrados, cada um corresponde ao LDR na mesma posição.

Ao lado é mostrado o diagrama dos LDRs e uma animação que ilustra como a leitura é feita na matriz. Coloca-se o pino 2 em nível alto e procede a leitura das entradas analógicas A0, A1, A2 e A3 armazenado os valores nas variáveis correspondentes ao primeiro, segundo, terceiro e quarto LDRs o mesmo acontece na segunda linha, pino 3, LDRs cinco a oito e na terceira linha, pino 4. LDRs nove a doze.

A montagem foi feita em uma placa perfurada padrão. Os diodos são 1N4148, mas podem ser substituídos por equivalentes. Eles são responsáveis em garantir que um LDR não interfira na leitura de outro. Os resistires são de 10 kohm.

Os programas foram baseados no exemplo SerialCallResponse que acompanha a IDE do Arduino. O exemplo ensina como enviar bytes do arduino a processing e do processing ao arduino. No programa abaixo o arduino envia 12 bytes, um para cada valor lido nos LDRs. Antes de ser enviado o valor é ajustado para um valor entre 0 e 255. O processing recebe os bytes e usa-os para determinar o tom de cinza do quadrado correspondente.

Programa para o arduino:

 const int ldr[4] = {A0, A1, A2, A3};  
 const int vccPin[3] = {2,3,4};  
 int ldrValue;  
 void setup() {  
  Serial.begin(19200);  
  pinMode(vccPin[0], OUTPUT);   
  pinMode(vccPin[1], OUTPUT);   
  pinMode(vccPin[2], OUTPUT);   
  estabeleceContato(); // Envia um byte "A" ate obter resposta do processing   
 }  
 void loop() {  
   for(int i = 0; i < 3; i++)  
   {  
    digitalWrite( vccPin[i],HIGH);  
      for(int j = 0; j < 4; j++)  
      {  
       ldrValue = analogRead(ldr[j]);  // le o LDR correspondente  
       ldrValue = constrain(ldrValue, 0, 800); // ajusta valor lido  
       ldrValue = map(ldrValue,0,800,0,255);  // ajusta valor lido  
       Serial.write(ldrValue); // envia valor via porta serial   
      }  
    digitalWrite( vccPin[i],LOW);  
   }           
 } // fim do loop principal  
 void estabeleceContato() {  
   while (Serial.available() <= 0) {  
   Serial.write('A');  // envia A ate estabelecer contato  
   delay(300);  
  }  
  }  


Programa para o Processing:

 // Adaptado do exemplo SerialCallResponse que acompanha a IDE do Arduino  
 import processing.serial.*;  
  int comando =0;  
  int y_01 = 55;  
 Serial myPort; // porta serial  
 int[] serialInArray = new int[12]; // vetor para armazenar o valores recebidos  
 int serialCount = 0;      // usado para contar o numero de bytes recebidos  
 int[] buffer = new int[12];  
 boolean firstContact = false; // Whether we've heard from the microcontroller  
 void setup() {  
  // imprime a lista de portas seriais  
  println(Serial.list());  
  String portName = Serial.list()[0];  
  // substituir COM9 pela porta onde esta o Arduino  
  myPort = new Serial(this, "COM9", 19200);   
  size(800, 600); //janela, largura, altura  
  background(0);  
  smooth();  
 }  
 void draw() {  
   stroke(255); // borda   
   fill(buffer[0]);    // determina a cor     
   rect(0, 0, 200, 200); // desenha o quadrado 1  
              // posicao x, posicao y, largura , altura  
   fill(buffer[1]);     
   rect(200, 0, 200, 200);   
   fill(buffer[2]);     
   rect(400, 0, 200, 200);    
   fill(buffer[3]);      
   rect(600, 0, 200, 200);    
   fill(buffer[4]);      
   rect(0, 200, 200, 200);   
   fill(buffer[5]);       
   rect(200, 200, 200, 200);    
   fill(buffer[6]);    
   rect(400, 200, 200, 200);  
   fill(buffer[7]);     
   rect(600, 200, 200, 200);  
   fill(buffer[8]);        
   rect(0, 400, 200, 200);   
   fill(buffer[9]);         
   rect(200, 400, 200, 200);  
   fill(buffer[10]);     
   rect(400, 400, 200, 200);  
   fill(buffer[11]);      
   rect(600, 400, 200, 200);   
 }  
 void serialEvent(Serial myPort) {  
  // le os bytes da porta serial  
  int inByte = myPort.read();  
  // se receber o primeiro byte e for 'A'  
  if (firstContact == false) {  
   if (inByte == 'A') {   
    myPort.clear();    // Limpa o buffer da porta serial  
    firstContact = true; // o primeiro contato ja ocorreu  
    myPort.write('A');  // envia "A" para que o arduino   
               // reconheça o primeiro contato  
   }   
  }   
  else {  
   // se não for o primeiro byte adiciona-o ao vetor:  
   serialInArray[serialCount] = inByte;  
   serialCount++;  
   // quando receber os 12 bytes armazena-os em buffer[i]  
   if (serialCount > 11) {  
    for(int i =0; i<12; i++)  
    {  
    buffer[i] = serialInArray[i];  
    }      
     // envia comandos caso existam  
    myPort.write(comando);  
    // Reset serialCount:  
    serialCount = 0;  
   }  
  }  
 }