sábado, 26 de agosto de 2017

Stepper motor 28BYJ48 vai e volta

Neste segundo post sobre o stepper 28BYJ48 a sketch apresentada implementou a ida e a volta do motor como funções.






 sketch:

int motorD1 = 2;    // Blue   - 28BYJ48 pin 1
int motorD2 = 3;    // Pink   - 28BYJ48 pin 2
int motorD3 = 4;    // Yellow - 28BYJ48 pin 3
int motorD4 = 5;    // Orange - 28BYJ48 pin 4
                    // Red    - 28BYJ48 pin 5 (VCC)


int lookupD[8] = {B01000, B01100, B00100, B00110, B00010, B00011, B00001, B01001};


void goForward();
void goReverse();
void setDOUT(int out);

void setup() 
{
  pinMode(motorD1, OUTPUT);
  pinMode(motorD2, OUTPUT);
  pinMode(motorD3, OUTPUT);
  pinMode(motorD4, OUTPUT);
  Serial.begin(9600);
  Serial.println("Hello, world! 28BYJ48 acordou!");
}


void loop() {
  goForward();
  delay(1000);
  goReverse();
  delay(1000);
}


void goForward()
{
    Serial.println("forward...");
    for( int i=0; i < 4096 ; i++){
      setDOUT(i%8);
      delay(1);
   }
}

void goReverse()
{
    Serial.println("reverse...");
    int j= 4096;
    for( int i=0; i < 4096 ; i++, j--){
      setDOUT(j%8);
      delay(1);
   }
}


void setDOUT(int out)
{
  int *p = lookupD;   
  digitalWrite(motorD1, bitRead(p[out], 0));
  digitalWrite(motorD2, bitRead(p[out], 1));
  digitalWrite(motorD3, bitRead(p[out], 2));
  digitalWrite(motorD4, bitRead(p[out], 3));
}


Girando o stepper motor 28BYJ48

Para ligar um stepper motor 28BYJ48 a um Arduino é necessário
um driver ULN2003. Conecte-os como abaixo:




Na sketch abaixo o delay de 800ms torna o giro muito lento e permitirá você visualizar o movimento nos leds. Depois de entender a lógica você poderá acelerar isso para 1ms.

A sketch manda uma mensagem pela usb para você visualizar no monitor que o arduino está vivo.

 Sketch:

int motorD1 = 2;    // Blue   - 28BYJ48 pin 1
int motorD2 = 3;    // Pink   - 28BYJ48 pin 2
int motorD3 = 4;    // Yellow - 28BYJ48 pin 3
int motorD4 = 5;    // Orange - 28BYJ48 pin 4
                    // Red    - 28BYJ48 pin 5 (VCC)

int lookup[8] = {B01000, B01100, B00100, B00110, B00010, B00011, B00001, B01001};

void setup() {
  pinMode(motorD1, OUTPUT);
  pinMode(motorD2, OUTPUT);
  pinMode(motorD3, OUTPUT);
  pinMode(motorD4, OUTPUT);
  Serial.begin(9600);
  Serial.println("Hello, world! 28BYJ48 acordou!");
}

void loop() {
   for( int i=0; i < 4096 ; i++){
        int out = i%8;
        digitalWrite(motorD1, bitRead(lookup[out], 0));
        digitalWrite(motorD2, bitRead(lookup[out], 1));
        digitalWrite(motorD3, bitRead(lookup[out], 2));
        digitalWrite(motorD4, bitRead(lookup[out], 3));;
        delay(800);  // lento para visualizar os leds, 1 é ok
        }
   delay(1000);
}

domingo, 2 de julho de 2017

Ligando várias teclas em uma unica entrada


E possível ligar botões e resistores em uma unica entrada analógica do Arduíno de modo ser possível que a sketch detecte qual tecla foi apertada. A montagem abaixo tem 4 teclas e utilizou resistores (de 10K, 1K, 4k7, 47k e 100k ( todos de 1/8 w) .

Montagem:



Sketch: A sketch abaixo identifica qual tecla foi apertada e se ficou apertada por longo tempo.

#define ADpin A1

void setup() {
  Serial.begin(9600);
  Serial.println("Hello, world! keyboard is ON.");
}

void loop() {
  int key = inkey();
  if(key>0) Serial.println(key);
  delay(1);     
}

int inkey()
{
        int s = analogRead(ADpin);
        if ( s> 70 && s < 110) return debounce(1,70,110);
        if ( s> 320 && s < 340) return debounce(2, 320,340);
        if ( s> 820 && s < 870) return debounce(3, 820,870);
        if ( s> 900 && s < 960) return debounce(4, 900, 960);
        return 0;
}

int debounce(int key, int a, int b){
  long timestart = millis();
  delay(20);
  while(analogRead(ADpin) > a && analogRead(ADpin) < b);
  long timeend = millis();
  if(timeend - timestart > 1000)
        return key*1000;
  else
        return key;
}

Resultado: No monitor vemos a teclas que foram apertadas. os valores maiores que 1000 correspondem a teclas que ficaram apertadas por muito tempo (tempo maior que 1 s).



quinta-feira, 29 de junho de 2017

Display com matriz de LEDs




Para escrever sketches para o display com matriz de LEDs usa-se a biblioteca MD_MAX72xx.

Esta biblioteca suporta diferentes hardwares. A versão que eu instalei vem configurada para o Parola. Mas o Hardware que eu tinha em mãos era um genérico compatível com FC16 e os nos exemplos que experimentei, os caracteres apareciam invertidos e os efeitos não funcionavam como o esperado. Foi necessário mudar a configuração.


Configurando: Localize e abra o arquivo MD_MAX72xx.h e mude as linhas abaixo:

#define USE_PAROLA_HW 0   // original é 1
#define USE_FC16_HW 1  // original é 0


sketch de teste "Hello, world!":

#include <MD_MAX72xx.h>

#define NUM_DEVICES 4

#define DATA_PIN 12  
#define CS_PIN 11  
#define CLK_PIN   10  


MD_MAX72XX mx = MD_MAX72XX(DATA_PIN, CLK_PIN, CS_PIN, NUM_DEVICES);


#define  DELAYTIME  100  

void scrollText(char *p)
{
  uint8_t charWidth;
  uint8_t cBuf[8];

  mx.clear();
  while (*p != '\0') 
  {
    charWidth = mx.getChar(*p++, sizeof(cBuf)/sizeof(cBuf[0]), cBuf);
    for (uint8_t i=0; i<charWidth + 1; i++)
    {
      mx.transform(MD_MAX72XX::TSL);
      if (i < charWidth)
        mx.setColumn(0, cBuf[i]);
      delay(DELAYTIME);
    }
  }
}

void setup()
{
  mx.begin();
}

void loop() 
{
   scrollText("Hello, world!           ");
   delay(2000);
}

domingo, 23 de abril de 2017

Driver para cargas de 12V com MOSFET


Este driver suporta um experimento de controle de temperatura. Alimentou uma resistência de aquecimento de 4,5 ohm. A ligação a um pino capaz de realizar saida em PWM permite controlar pelo programa a potência aplicada a resistência. Para ativar um pino por PWM a sketch utiliza a função analogWrite().


A sketch de teste do circuito pode ser utilizada sem a carga pois o LED funcina como um indicador da potencia aplicada a carga.

#define PIN_CARGA 5          // the pino PWM pino ao qual esta concetada a PIN_CARGA e o LED
int potencia = 0;    // potencia na PIN_CARGA
int incremento = 5;    // incremento de potencia na PIN_CARGA

void setup() 
{
        pinMode(PIN_CARGA, OUTPUT);
}

void loop() 
{
  analogWrite(PIN_CARGA, potencia);
  potencia = potencia + incremento;
  if (potencia <= 0 || potencia >= 255) 
          incremento = -incremento;
  delay(30);
}

domingo, 26 de março de 2017

Decifrando o controle remoto da TV

Para receber comandos de um controle remoto de TV é necessário um receptor de IR (infra vermelho). A figura abaixo mostra um módulo sensor IR para Arduino que é um receptor infravermelho.

Módulo sensor de infravermelho


Hardware: É relativamente fácil conectar o receptor de IR com o Arduino. Este experimento mostra a montagem de um protótipo com Arduino Uno. A montagem do hardware é conforme a figura abaixo. Verifique se os três pinos de Vcc, GND e sinal do seu módulo são iguais a este módulo usado na figura)





Sketch:  A sketch abaixo decifra as teclas de um controle remoto de TV,  apresentando o código da tecla apertada no controle remoto na tela do monitor da IDE do Arduino. Observe que a sketch usa a biblioteca IRremote que pode ser obtida aqui.

#include <IRremote.h>

int RECV_PIN = 11;

IRrecv irrecv(RECV_PIN);
decode_results resultado;

unsigned long last = millis();


void setup()
{
  irrecv.enableIRIn(); // Inicia recepção
  Serial.begin(9600);
  Serial.println("Decodificador de Controle Remoto");
}


void loop() {
  if (irrecv.decode(&resultado)) {
    if (millis() - last > 250) {
      mostra(&resultado);
    }
    last = millis();      
    irrecv.resume(); // proximo valor
  }
}

void mostra(decode_results *resultado) {
  if (resultado->decode_type == UNKNOWN) {
    Serial.println("Controle não identificado.");
  } 
  else {
    if (resultado->decode_type == NEC) {
      Serial.print("Identificado  NEC: ");
    } else if (resultado->decode_type == SONY) {
      Serial.print("Identificado  SONY: ");
    } else if (resultado->decode_type == RC5) {
      Serial.print("Identificado  RC5: ");
    } else if (resultado->decode_type == RC6) {
      Serial.print("Identificado  RC6: ");
    } else if (resultado->decode_type == DISH) {
      Serial.print("Identificado  Dish: ");
    } else if (resultado->decode_type == SHARP) {
      Serial.print("Identificado  Sharp: ");
    } else if (resultado->decode_type == PANASONIC) {
      Serial.print("Identificado  Panasonic: ");
    } else if (resultado->decode_type == JVC) {
      Serial.print("Identificado  JVC: ");
    } else if (resultado->decode_type == SANYO) {
      Serial.print("Identificado  Sanyo: ");
    } else if (resultado->decode_type == MITSUBISHI) {
      Serial.print("Mistubishi: ");
    } else if (resultado->decode_type == SAMSUNG) {
      Serial.print("Identificado  Samsung: ");
    } else if (resultado->decode_type == LG) {
      Serial.print("Identificado  LG: ");
    }

    Serial.print(resultado->value, HEX);
    Serial.print(" (");
    Serial.print(resultado->bits, DEC);
    Serial.println(" bits)");
  }
}

Visualização do resultado: Quando a sketch foi testada com dois controles remotos diferentes intercalados o monitor apresentou os resultado abaixo:




O que você pode fazer agora: Você gostaria de incluir o controle remoto em um projeto seu? Então, anote os códigos das teclas que seriam úteis para construir o seu projeto com controle remoto e faça uma sketch que interprete e execute os comandos de controle.

sábado, 18 de fevereiro de 2017

Medindo a temperatura com um termistor

O hardware do projeto. O circuito do termistor utilizado neste projeto corresponde ao circuito presente na placa shield RAMPS 1.4 para Arduino Mega. É composto por um resistor de 4k7  formando  um divisor de tensão com um termistor de 100k. Um filtro com capacitor 100nF e resitor de 100k conecta o divisor de tensão a porta analógica do  Arduino(A0). O circuito está ilustrado no fritzing abaixo.


Leitura da porta A0: A leitura da Porta A0 é uma medida de temperatura, mas por causa das caracteristicas do termistor não é linear e nem está em graus centigrados. Uma conversão para graus centigrados deve ser realizada.

Conversão para °C: Como falta uma fórmula matemática para esta conversão para graus centígrados, a maneira de realizá-la é utilizando uma tabela de valores aferidos e depois calcular a medida interpolando valores de duas linha da tabela.

Criação da Tabela. Alguém precisa criar uma tabela, que normalmente é levantada por aferição da tempertura com termometro preciso. Na construção da tabela, para cada leitura da porta analógica do Arduino, deve-se registrar a temperatura no termõmetro. Tem uma tabela pronta lá embaixo que foi contruída para termistores de 100k bastante utilizados nas medições de temperatura de impressoras 3D open source e serve para o circuito do projeto. Se o seu termistor é diferente, você terá que obter a tabela.

Exemplo 1 de conversão: Se a leitura da porta A0 for 205, conforme a tabela abaixo a temperatura corrrespondente é 165°C.

Exemplo 2 de conversão:  Se a leitura da porta A0 for  135, conforme a tabela abaixo a temperatura deve estar entre 190°C e 185°C. O valor exato será:

190 + (135-131)*(185-190)/(143-131) = 188,33 °C

Cálculo: O cálculo do valor foi realizado por interpolação na tabela. Se você se interessar pesquise sobre como interpolar.

Tabela de conversão Leitura digital na porta A0 para °C

A0°CA0°CA0°C
23300109200591100
2529512019562895
2729013119066590
2828514318570285
3128015618073780
3327517117577075
3527018717080170
3826520516583065
4126022416085760
4425524515588155
4825026815090350
5224529314592245
5624032014093940
6123534813595435
6623037913096630
7122541112597725
7822044512098520
8421548011599315
9221051611099910
10020555310510045
10080


Sketch A sketch Arduino abaixo realiza a leitura, converte e envia para o computador via monitor serial 1 vez a cada segundo.

\\ tabela de conversão AD para graus centígrados
const short temptable[][2] = {   
{       23 ,       300     },
{       25 ,       295     },
{       27 ,       290     },
{       28 ,       285     },
{       31 ,       280     },
{       33 ,       275     },
{       35 ,       270     },
{       38 ,       265     },
{       41 ,       260     },
{       44 ,       255     },
{       48 ,       250     },
{       52 ,       245     },
{       56 ,       240     },
{       61 ,       235     },
{       66 ,       230     },
{       71 ,       225     },
{       78 ,       220     },
{       84 ,       215     },
{       92 ,       210     },
{       100 ,       205     },
{       109 ,       200     },
{       120 ,       195     },
{       131 ,       190     },
{       143 ,       185     },
{       156 ,       180     },
{       171 ,       175     },
{       187 ,       170     },
{       205 ,       165     },
{       224 ,       160     },
{       245 ,       155     },
{       268 ,       150     },
{       293 ,       145     },
{       320 ,       140     },
{       348 ,       135     },
{       379 ,       130     },
{       411 ,       125     },
{       445 ,       120     },
{       480 ,       115     },
{       516 ,       110     },
{       553 ,       105     },
{       591 ,       100     },
{       628 ,       95      },
{       665 ,       90      },
{       702 ,       85      },
{       737 ,       80      },
{       770 ,       75      },
{       801 ,       70      },
{       830 ,       65      },
{       857 ,       60      },
{       881 ,       55      },
{       903 ,       50      },
{       922 ,       45      },
{       939 ,       40      },
{       954 ,       35      },
{       966 ,       30      },
{       977 ,       25      },
{       985 ,       20      },
{       993 ,       15      },
{       999 ,       10      },
{       1004 ,       5       },
{       1008 ,       0       }
};

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

void loop() {
  short a = 0 ;
  int i;
  float celsius;
  a = analogRead(A1) ;
  for (i=1; i<sizeof(temptable)/(2*sizeof(short)); i++) {
      if ( temptable[i][0] > a){ // calculo interpolação
        celsius = temptable[i-1][1] + (a - temptable[i-1][0]) * (
          (float)(temptable[i][1] - temptable[i-1][1]) /
          (float)(temptable[i][0] - temptable[i-1][0]));
        break;
      }
  }
  Serial.print( a ); // enviando medidas de temperatura para monitor
  Serial.print( " - ");
  Serial.print(celsius);
  Serial.println( " C");
  delay(1000);
}


Visualizaçao do resultado: Visualização da saída do programa no monitor é conforme a figura abaixo: