Publicidade:

terça-feira, 14 de novembro de 2017

Arduino - Botão com múltiplas funções

Nesse vídeo mostro como executar em um único botão diversas funções distintas.

Vídeo


Código-fonte
byte inputPin = 10;
byte ledPin = 13;
byte redPin = 6;
byte greenPin = 4;
byte bluePin = 3;


byte digitalReadOnce(byte val){
  static byte lastVal = HIGH;
  static unsigned long m = 0;
  if (lastVal != val && millis() > (m+100) ) { //M+100 -->DEBOUNCING 100ms
    lastVal = val;
    m = millis();
    return lastVal;
  } 
  return HIGH;
}

int getCommand(){
  static unsigned long m1 = 0;  //millis no momento inicia de pressionar o botão 
  static unsigned long m2 = 0;  //millis após soltar o botão 
  static byte count = 0;
  
  byte r = digitalRead(inputPin);
  
  if (digitalReadOnce(r) == LOW){
    m1 = millis();
    count++;
  }
  
  if (r == LOW){
    m2 = millis();
  } else {
    if (! (m2>0 && m2-m1 < 1000) ){  //o botão deve ser pressionado por menos de 1 segundo, senão cancela o comando
      count = 0;
      m1 = 0;
      m2 = 0;
    }
    
    if (m2>0 && millis()-m2 > 1500){  //após a ultima vez pressionado o botao, aguarda 1,5 segundos para finalizar e retornar o comando.
      byte c = count;
      count = 0;
      m1 = 0;
      m2 = 0;
      
      return c;
    }
  }
  
  return 0;
}


void setup() {
  Serial.begin(9600);
  pinMode(inputPin, INPUT_PULLUP); //internal pullup resistor is used to simplify the circuit
  pinMode(bluePin, OUTPUT);
  pinMode(greenPin, OUTPUT);
  pinMode(redPin, OUTPUT);
  pinMode(ledPin,OUTPUT);
}

void loop() {
  
  int command = getCommand();

  if (command == 1){
    digitalWrite(redPin, !digitalRead(redPin));
  }
  
  if (command == 2){
    digitalWrite(greenPin, !digitalRead(greenPin));
  }
  
  if (command == 3){
    digitalWrite(bluePin, !digitalRead(bluePin));
  }
  
  if (command == 4){
    digitalWrite(redPin, HIGH);
    digitalWrite(greenPin, HIGH);
    digitalWrite(bluePin, HIGH);
  }
  
  if (command == 5){
    digitalWrite(redPin, LOW);
    digitalWrite(greenPin, LOW);
    digitalWrite(bluePin, LOW);
  }
  
  digitalWrite(ledPin, !digitalRead(inputPin));
  
  delay(10);  //apenas utilizado no simulador
}







Comandos via LDR

Baseado no exemplo anterior, foi substituido o botão por um LDR, onde é possível enviar comandos pro Arduino através de luz.

Vídeo:


Código-Fonte:
byte ledPin = 13;
byte redPin = 6;
byte greenPin = 4;
byte bluePin = 3;


boolean hasLightOnce(byte val){
  static boolean lastVal = false;
  static unsigned long m = 0;
  if (lastVal != val && millis() > (m+100) ) { //M+100 -->DEBOUNCING 100ms
    lastVal = val;
    m = millis();
    return lastVal;
  } 
  return false;
}

boolean hasLight(){
  return (analogRead(A0) < 100);
}


int getCommand(){
  static unsigned long m1 = 0;  //millis no momento inicia de pressionar o botão 
  static unsigned long m2 = 0;  //millis após soltar o botão 
  static byte count = 0;
  
  boolean light = hasLight();
  
  if (hasLightOnce(light)){
    m1 = millis();
    count++;
  }
  
  if (light){
    m2 = millis();
  } else {
    if (! (m2>0 && m2-m1 < 1000) ){  //o botão deve ser pressionado por menos de 1 segundo, senão cancela o comando
      count = 0;
      m1 = 0;
      m2 = 0;
    }
    
    if (m2>0 && millis()-m2 > 1500){  //após a ultima vez pressionado o botao, aguarda 1,5 segundos para finalizar e retornar o comando.
      byte c = count;
      count = 0;
      m1 = 0;
      m2 = 0;
      
      return c;
    }
  }
  
  return 0;
}


void setup() {
  Serial.begin(9600);
  pinMode(bluePin, OUTPUT);
  pinMode(greenPin, OUTPUT);
  pinMode(redPin, OUTPUT);
  pinMode(ledPin,OUTPUT);
}

void loop() {
  
  int command = getCommand();

  if (command == 1){
    digitalWrite(redPin, !digitalRead(redPin));
  }
  
  if (command == 2){
    digitalWrite(greenPin, !digitalRead(greenPin));
  }
  
  if (command == 3){
    digitalWrite(bluePin, !digitalRead(bluePin));
  }
  
  if (command == 4){
    digitalWrite(redPin, HIGH);
    digitalWrite(greenPin, HIGH);
    digitalWrite(bluePin, HIGH);
  }
  
  if (command == 5){
    digitalWrite(redPin, LOW);
    digitalWrite(greenPin, LOW);
    digitalWrite(bluePin, LOW);
  }
  
  digitalWrite(ledPin, hasLight() );
  
  delay(10);  //apenas utilizado no simulador
}






sexta-feira, 3 de novembro de 2017

Arduino - Charlieplex com botões

Demonstração de como utilizar vários botões com poucos pinos através da multiplexação Charlieplex.

Vídeo:



Código-fonte:
#define NUM_PINS 4

const int pins[] = {2,3,4,5};

void init_pins(){
  for (int i = 0; i< NUM_PINS; i++) { 
    pinMode(pins[i], INPUT_PULLUP); 
    digitalWrite(pins[i], HIGH);
  }
}

byte readCharlieplexButons(int pin1, int pin2){
  init_pins();
  pinMode(pin1, OUTPUT);
  digitalWrite(pin1, LOW);
  return !digitalRead(pin2);
}

int getButton(){
  byte index_button = 0;
  for (int i=0; i<NUM_PINS; i++) { 
    for (int j=i+1; j<NUM_PINS; j++) { 
      if (i!=j) { 
        if (readCharlieplexButons(pins[j], pins[i])) {
          return index_button;
        }
        index_button++;
        if (readCharlieplexButons(pins[i], pins[j])) {
          return index_button;
        }
        index_button++;
      }
    }
  }
  return -1;  //-1 --> nenhum botão pressionado
}
  
int getButtonOnce(){
  static int lastVal = -1;
  static unsigned long m = 0;
  int val = getButton();
  if (lastVal != val && millis() > (m+100) ) { //M+100 -->DEBOUNCING 100ms
    lastVal = val;
    m = millis();
    return lastVal;
  } 
  return -1;
}


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

void loop() { 
  int button = getButtonOnce();
  if ( button >=0){
    Serial.println(button);
  }
  delay(10);   //necessário apenas no simulador.
}


terça-feira, 31 de outubro de 2017

Arduino - Teclado 4x4 (keypad)

Como ligar um teclado 4x4 no Arduino sem o uso de biblioteca

Vídeo:


Código-fonte:
byte rows[] = {11,10,9,8};
byte columns[] = {7,6,5,4};

char getKey(){
  char keys[4][4] = {
    {'1','2','3','A'},
    {'4','5','6','B'},
    {'7','8','9','C'},
    {'*','0','#','D'}
  };
  
  char k = '\0';
  
  for (int r=0; r<4; r++){
    digitalWrite(rows[r], LOW);
    
    for (int c=0; c<4; c++){
      if (digitalRead(columns[c]) == LOW){
        k = keys[r][c];
        break;
      }
    }
    
    digitalWrite(rows[r], HIGH);
    
    if (k) {
      break;
    }
  }
  
  return k;
}

char getKeyOnce(){
  static char lastVal = '\0';
  static unsigned long m = 0;
  char val = getKey();
  if (lastVal != val && millis() > (m+100) ) { //M+100 -->DEBOUNCING 100ms
    lastVal = val;
    m = millis();
    
    return lastVal;
  } 
  return '\0';
}

void setup() {
  for (int i=0; i<4; i++){
    pinMode(rows[i], OUTPUT);
    pinMode(columns[i], INPUT_PULLUP);
    
    digitalWrite(rows[i], HIGH);
  }
  
  Serial.begin(9600);
}

void loop(){
  
  char k = getKeyOnce();
  if (k) {
    Serial.println(k);
  }
  
  delay(10); //apenas para o simulador. 
}



Exemplo de uma Calculadora utilizando keypad 4x4:


Código-fonte:
#include <LiquidCrystal.h>

LiquidCrystal lcd(13, 12, 11, 10, 9, 8);

byte rows[] = {5,4,3,2};
byte columns[] = {A5,A4,A3,A2};

String valor1 = "";
String valor2 = "";
String resultado = "";
char operacao = '\0';

char getKey(){
  char keys[4][4] = {
    {'1','2','3','A'},
    {'4','5','6','B'},
    {'7','8','9','C'},
    {'*','0','#','D'}
  };
  char k = '\0';
  for (int r=0; r<4; r++){
    digitalWrite(rows[r], LOW);
    for (int c=0; c<4; c++){
      if (digitalRead(columns[c]) == LOW){
        k = keys[r][c];
        break;
      }
    }
    digitalWrite(rows[r], HIGH);
    if (k) { break; }
  }
  return k;
}

char getKeyOnce(){
  static char lastVal = '\0';
  static unsigned long m = 0;
  char val = getKey();
  if (lastVal != val && millis() > (m+100) ) { //M+100 -->DEBOUNCING 100ms
    lastVal = val;
    m = millis();
    
    return lastVal;
  } 
  return '\0';
}

void setup() {
  lcd.begin(16, 2);
  
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("youtube.com/");
  lcd.setCursor(0, 1);
  lcd.print("fabianoallex");
  
  for (int i=0; i<4; i++){
    pinMode(rows[i], OUTPUT);
    pinMode(columns[i], INPUT_PULLUP);
    digitalWrite(rows[i], HIGH);
  }
  
  delay(3000);
  
  lcd.clear();
  lcd.setCursor(0, 0);
}

void loop() {
  execKeypad();
  delay(10); //apenas para o simulador. 
}

void execKeypad(){
  char operacoes[] = {'\0', '*', '/', '+', '-'};
  static byte indexOperacao = 0;
  char k = getKeyOnce();
  
  if (k) {
    if (k >= 48 && k<= 57) {  /*digitos numericos*/
      resultado = "";
      if (operacao){
        valor2 = valor2 + k;
      } else {
        valor1 = valor1 + k;
      }
    }
    
    if (k == '*') {
      if (resultado != "" && valor1 == ""){
        valor1 = resultado;
        resultado = "";
      }
      indexOperacao++;
      if (indexOperacao > 4){ indexOperacao = 0; }
      operacao = operacoes[indexOperacao];
    }
    
    if (k == '#' && valor1 != "" && valor2 != "") {
      double v1, v2, r;
      
      char vchar[10];
      valor1.toCharArray(vchar, 10);
      v1 = atof(vchar); 
      valor2.toCharArray(vchar, 10);
      v2 = atof(vchar); 
      
      if (operacao == '*') { r = v1 * v2; }
      if (operacao == '+') { r = v1 + v2; }
      if (operacao == '-') { r = v1 - v2; }
      if (operacao == '/') { r = (v2 == 0) ? 0 : v1 / v2; }
      
      sprintf(vchar, "%d.%02d", (int)r, (long)(abs(r)*100)%100);
      resultado = (operacao == '/' && r == 0) ? "Div 0" : String(vchar);
      
      valor2 = "";
      valor1 = "";
      indexOperacao = 0;
      operacao = '\0';
    }
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print(resultado != "" ? resultado : valor1);
    
    lcd.setCursor(0, 1);
    lcd.print(valor2);
    
    lcd.setCursor(15, 0);
    lcd.print(operacao ? operacao : ' ');
  }
}

quarta-feira, 24 de agosto de 2016

Arduino - Utilizando módulo Joystick

Demonstração do uso de um módulo joystick com Arduino.

O módulo possui 5 pinos: gnd, vcc, pino do botão e mais dois pinos analógicos dos eixos x e y.

Os pinos analógicos nada mais são do que dois potenciômetros ligados nas portas analógicas do Arduino. Caso não saiba como é feita a leitura de um potenciômetro, é interessante aprender antes.

Vídeo:




Código-fonte:

#include <LiquidCrystal_I2C.h>

/*************************************************************************************************************
************************************CLASSE JOYSTICK***********************************************************
*************************************************************************************************************/
class Joystick {
  private:
    boolean _isTop    : 1;
    boolean _isBottom : 1;
    boolean _isLeft   : 1;
    boolean _isRight  : 1;
    unsigned int _x   : 10;
    unsigned int _y   : 10;
    byte _pinX;
    byte _pinY;
    byte _pinZ;
    float _angle;
  public:
    Joystick(int pinX, int pinY, int pinZ){
      _pinX = pinX;
      _pinY = pinY;
      _pinZ = pinZ;
      pinMode(pinX, INPUT);
      pinMode(pinY, INPUT);
      pinMode(pinZ, INPUT_PULLUP);
    }
    update() {
      _x = analogRead(_pinX);
      _y = analogRead(_pinY);
      _isTop    = (_y < 200);
      _isBottom = (_y > 800);
      _isRight  = (_x < 200);
      _isLeft   = (_x > 800);

      float distX = 0;
      float distY = 0;

      if (_x < 480) { distX = 480 - _x; }
      if (_x > 525) { distX = 525 - _x; }
      if (_y < 480) { distY = 480 - _y; }
      if (_y > 525) { distY = 525 - _y; }

      if (!(distX == 0 && distY == 0)){
        _angle = degrees(atan2(distY, distX));    //degrees --> converte de radianos (retornado por atan2) para graus
      } else {
        _angle = 0;
      }

      if (_angle < 0) { _angle = _angle + 360; }
    }
    boolean isTop()      { return _isTop; }
    boolean isBottom()   { return _isBottom; }
    boolean isLeft()     { return _isLeft; }
    boolean isRight()    { return _isRight; }
    unsigned int readX() { return _x; }
    unsigned int readY() { return _y; }
    float readAngle()    { return _angle; }
    byte buttonRead()    { return digitalRead(_pinZ); }

    byte readTop() { if (_y < 480) { return map(_y, 480, 0, 0, 255); } return 0; }
    byte readBottom() { if (_y > 525) { return map(_y, 525, 1023, 0, 255); } return 0; }
    byte readLeft() { if (_x > 525) { return map(_x, 525, 1023, 0, 255); } return 0; }
    byte readRight() {if (_x < 480) { return map(_x, 480, 0, 0, 255); } return 0;}
};
/*************************************************************************************************************
************************************FIM CLASSE CLASSE JOYSTICK************************************************
*************************************************************************************************************/
  
Joystick joystick(A1, A2, A0);   //pino analogico eixo x,   pino analógico eixo y,   pino digita botão
LiquidCrystal_I2C lcd(0x3F,20,4);

void setup() {
  Serial.begin(9600);
  lcd.init();
  lcd.backlight();

  byte c0[8] = {B00100,  B01110,  B10101,  B00100,  B00100,  B00100,  B00100,  B00000 };  //seta cima
  byte c1[8] = {B00100,  B00100,  B00100,  B00100,  B10101,  B01110,  B00100,  B00000 };  //seta baixo
  lcd.createChar(0, c0);  
  lcd.createChar(1, c1);  
}

void loop() {
  
  static unsigned long mref = 0;
  if (millis() - mref > 500) {
    mref = millis();
    
    joystick.update();             //antes de fazer a leitura dos valores, é necessário chamar o update. 
    
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print((int)joystick.readAngle());
    lcd.write(223);

    lcd.setCursor(8,0);
    
    if (joystick.isTop()) { lcd.write(0); }
    if (joystick.isBottom()) { lcd.write(1); }
    if (joystick.isLeft()) { lcd.write(127); }
    if (joystick.isRight()) { lcd.write(126); }

    lcd.setCursor(0,1);
    lcd.print("x: ");
    lcd.print(joystick.readX());
    lcd.setCursor(8,1);
    if (joystick.readLeft() > 0) { 
      lcd.print("left: ");
      lcd.print(joystick.readLeft());  //mostra a leitura analógica para a esquerda de 0 a 255
    }
    if (joystick.readRight() > 0) { 
      lcd.print("right: ");
      lcd.print(joystick.readRight()); //mostra a leitura analógica para a direita de 0 a 255
    }
    
    lcd.setCursor(0,2);
    lcd.print("y: ");
    lcd.print(joystick.readY());
    lcd.setCursor(8,2);
    if (joystick.readTop() > 0) { 
      lcd.print("top: ");
      lcd.print(joystick.readTop()); //mostra a leitura analógica para cima de 0 a 255
    }
    if (joystick.readBottom() > 0) { 
      lcd.print("bottom: ");
      lcd.print(joystick.readBottom()); //mostra a leitura analógica para baixo de 0 a 255
    }

    lcd.setCursor(0,3);
    lcd.print("z: ");
    lcd.print(joystick.buttonRead());  //mostra se o botão (eixo z) foi pressionado
    
  }
}