quarta-feira, 1 de junho de 2011

Atmega328 - Pulse-width modulation (PWM)

Processing – Controlando o Atmega328 com PWM no Standard Firmata

Este pequeno tutorial descreve os passos que fiz para construir a interface de controle do motor e um led pelo computador. O primeiro passo é fazer o upload do código “Standard Firmata” para o Atmega Arduino. Este código está na sessão da biblioteca Firmata da IDE Arduino, é uma versão do firmware específico para controle pelo Processing. Após o upload, nenhum comando funcionará direto no Arduino, os comandos deverão ser passados através da codificação no Processing pela porta serial.

O Arduino foi montado em uma Protoboard seguindo o esquema descrito a seguir, para acesso ao computador utilizei um conversor USB-TTL, este conversor possibilita o acesso pela porta USB com o Arduino e pode ser encontrado facilmente na Internet. Comprei o meu por R$ 26,00.




Pulse-width modulation (PWM) pode ser desenvolvido no Arduino de vários modos. O texto a seguir mostra de forma simples de como usar essa técnica para controlar a velocidade de um pequeno motor e um led através do computador. O código no Processing utiliza a mesma estrutura do exemplo proposto no exemplo “Fade” do Arduino.

/*
 Fade

 This example shows how to fade an LED on pin 9
 using the analogWrite() function.

 This example code is in the public domain.

 */
int brightness = 0;    // how bright the LED is
int fadeAmount = 5;    // how many points to fade the LED by

void setup()  {
  // declare pin 9 to be an output:
  pinMode(9, OUTPUT);
}

void loop()  {
  // set the brightness of pin 9:
  analogWrite(9, brightness);   

  // change the brightness for next time through the loop:
  brightness = brightness + fadeAmount;

  // reverse the direction of the fading at the ends of the fade:
  if (brightness == 0 || brightness == 255) {
    fadeAmount = -fadeAmount ;
  }    
  // wait for 30 milliseconds to see the dimming effect   
  delay(30);                           
}


O que é PWM?

A Modulação por largura de pulso (MLP) - mais conhecida pela sigla em inglês "PWM" (Pulse-Width Modulation). Também é utilizada para variar o valor da transferência de potência entregue a uma carga sem as perdas ocorridas normalmente devido à queda de tensão por recursos resistivos. Em um sistema PWM, a chave de estado sólido (normalmente IGBT, MOSFET ou transistor bipolar) usada para controlar o fluxo de corrente: ora não conduzindo corrente, ora conduzindo, mas provocando uma queda de tensão muito baixa; como a potência instantânea dissipada pela chave é o produto da corrente pela tensão elétrica a um dado instante, isso significa que nenhuma potência é dissipada se a chave fosse uma chave "ideal". Com uma taxa de modulação suficientemente elevada, simples filtros RC são freqüentemente utilizados para suavizar o trem de pulsos em uma tensão analógica estável. Esse método é normalmente empregado no controle de velocidade de motores de corrente contínua.

Origem: Wikipédia, a enciclopédia livre.


Neste projeto, eu controlo um pequeno motor de corrente contínua de 6 Volts através de um MOSFET utilizando o PWM do arduino e também exibo o valor referente à velocidade na tela do computador. O controle da velocidade é feito por um programa no Processing, que se comunica com o arduino através da porta serial e envia valores para a mudança da velocidade. Esses valores variam de 0 a 255.


A seguir, veja o desenho na Protoboard de todos os componentes eletrônicos para o projeto.


=============================================================================


Na programação, criei dois módulos, o primeiro com os comandos para o controle no Arduino e o segundo com a classe de controle dos botões.

ArduinoControlPotMotors.pde
ClassButtons.pde

A codificação é auto descritiva para quem já conhece a linguagem, quem ainda não está familiarizado pode acessar os Sites para mais informações.


Abs, Marcelo Victorio A. Costa.

ArduinoControlPotMotors.pde

// By Marcelo Victorio A. Costa
// 23/06/2011

import processing.serial.*;
import cc.arduino.*;

Porta serial para a comunicação com o arduino;
    //[0] "COM1"
    //[1] "COM3"
int pCOM = 1;
int pino_led = 7;
int pino_sensor_Pot = 3;
int valor_capturado_Pot = 0;
PFont arial;

int w = width;
int h = height;

Cbutton CB1 = new Cbutton(600, 450, 80, 30,"Led1");
Cbutton CB2 = new Cbutton(700, 450, 80, 30,"Exit");

void setup()
{
    size(screen.width / 2, screen.height / 2);

    background(0);
    ellipseMode(CENTER);
    println(Arduino.list());

    arduino = new Arduino(this, Arduino.list()[pCOM], 57600);
    arduino.pinMode(pino_sensor_Pot, Arduino.INPUT);
    arduino.pinMode(pino_led, Arduino.OUTPUT);
    arial = createFont("Arial",50);

    println(width); 
}

void draw()
{
   // captura o valor do potenciômetro
    valor_capturado_Pot = arduino.analogRead(pino_sensor_Pot);

    background(200);
    // usa o valor capturado para alterar o diâmetro do círculo

    fill(255,80,80);
    ellipse(width / 2, height / 2,  valor_capturado_Pot/2,  valor_capturado_Pot/2);
     
    //println(valor_capturado_Pot);
    //println(height);

    textFont(arial);
    fill(0,0,0);    
    text(valor_capturado_Pot/4,50,80);
   
    delay(100);
   
    arduino.analogWrite(9,valor_capturado_Pot / 4);
   
    //Buttons Control
   
    if (CB1.button()) {
       arduino.digitalWrite(pino_led, Arduino.HIGH);   // set the LED on
    }
    else{
      arduino.digitalWrite(pino_led, Arduino.LOW);    // set the LED off     
    }

    if (CB2.button()) {
      exit();
    }

}

ClassButtons.pde
// By Marcelo Victorio A. Costa
// 23/06/2011

class Cbutton {
  int bx, by, bs, bt;
  String sNome;
  boolean locked = false;
  PFont arialButtons;

  Cbutton (int pbx, int pby, int pbs, int pbt, String psNome) {
   
      bx = pbx;
      by = pby;
      bs = pbs;
      bt = pbt;  
      sNome = psNome;
    }
      
    boolean button() {

      arialButtons = createFont("Arial",15);
      textFont(arialButtons);

      // Test if the cursor is over the box
       if (mouseX > bx && mouseX < bx+bs && mouseY > by && mouseY < by+bt) {
        
           drawbutton(255);
   
           if (mousePressed && (mouseButton == LEFT)) {
               drawbutton(225);
               locked = true;
           }else{
               locked = false;
           }
       }else{ 
        drawbutton(150);
        locked = false;
       }
     return locked;
    }

    void drawbutton(int pCollor) {
     
      stroke(100);
      fill(pCollor);
      rect(bx, by, bs, bt);
      fill(0);
      text(sNome,bx+25,by+20);  
    }


}