Publicidade:

domingo, 3 de maio de 2015

Arduino - Ponte H para Motor - IBT 2 - BTS7960

Demonstração de uso da Ponte H IBT 2






Especificações
  • Tensão: 6V-27V
  • Corrente: 43A
  • Input level: 3.3V-5V

pinos

1 - PWM Direção 1
2 - PWM Direção 2
3 - Ativar / Desativar PWM Direção 1 - HIGH ativa
4 - Ativar / Desativar PWM Direção 2 - HIGH ativa
5 - Direção 1 - Side Currente Alarm Output
6 - Direção 2 - Side Currente Alarm Output
7 - VCC
8 - Ground


Para o teste foram utilizados os seguintes pinos

1 - Ligado ao pino 5 (PWM) do Arduino
2 - Ligado ao pino 6 (PWM) do Arduino
3 - VCC
4 - VCC
5 - Desconectado
6 - Desconectado
7 - VCC
8 - Ground


Código-Fonte:

/*
IBT-2 Motor Control Board driven by Arduino.
 
Speed and direction controlled by a potentiometer attached to analog input 0.
One side pin of the potentiometer (either one) to ground; the other side pin to +5V
 
Connection to the IBT-2 board:
IBT-2 pin 1 (RPWM) to Arduino pin 5(PWM)
IBT-2 pin 2 (LPWM) to Arduino pin 6(PWM)
IBT-2 pins 3 (R_EN), 4 (L_EN), 7 (VCC) to Arduino 5V pin
IBT-2 pin 8 (GND) to Arduino GND
IBT-2 pins 5 (R_IS) and 6 (L_IS) not connected
*/
 
int SENSOR_PIN = A0; // center pin of the potentiometer
 
int RPWM_Output = 5; // Arduino PWM output pin 5; connect to IBT-2 pin 1 (RPWM)
int LPWM_Output = 6; // Arduino PWM output pin 6; connect to IBT-2 pin 2 (LPWM)
 
void setup() {
  pinMode(RPWM_Output, OUTPUT);
  pinMode(LPWM_Output, OUTPUT);
}
 
void loop() {
  int sensorValue = analogRead(SENSOR_PIN);
 
  // sensor value is in the range 0 to 1023
  // the lower half of it we use for reverse rotation; the upper half for forward rotation
  if (sensorValue < 512)
  {
    // reverse rotation
    int reversePWM = -(sensorValue - 511) / 2;
    analogWrite(LPWM_Output, 0);
    analogWrite(RPWM_Output, reversePWM);
  } else {
    // forward rotation
    int forwardPWM = (sensorValue - 512) / 2;
    analogWrite(LPWM_Output, forwardPWM);
    analogWrite(RPWM_Output, 0);
  }
}


Referência: http://www.hessmer.org/blog/wp-content/uploads/2013/12/IBT-2-Input-Ports.jpg

sexta-feira, 1 de maio de 2015

Arduino - Teclado 4x4 com Pino Analógico








Esquema

Os botões devem ser ligados conforme imagem abaixo, de forma que um dos terminais de cada um dos botões estejam em um linha e o outro terminal em uma coluna.



Montagem do circuito na PCB

Atenção!!

O teclado que eu utilizei, foi retirado de um ponto eletrônico portátil que não estava mais sendo usado. Não sei se ele tem a mesma construção de outros teclados, principalmente destes vendidos para ser utilizado com o Arduino, portanto, talvez sejam necessárias algumas alterações, para rodar com outros teclados.

Inicialmente a placa foi feita sem o capacitor representado no circuito acima, mas durante os testes percebi que ainda haviam oscilações que retornavam leituras com valores errados. Pra tentar minimizar as leituras erradas inclui o capacitor de 100nF.








Para testar a placa primeiramente rodei o código abaixo para identificar o valor lido em cada uma das teclas. Ao executar é verificada uma oscilação entre leituras de um mesmo botão, não sendo possível identificar o valor correto para cada botão.


Código 01


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

void loop() {
   Serial.println(analogRead(A5));
   delay(100);
}





Para tentar chegar em um valor mais aproximado do real, rodeio o código abaixo, no qual faço a leitura 200 vezes, e depois faço a média de todos esses valores, chegando então em um valor que dá um retorno com menos variações.

código 02:

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

void loop() {
  const int LEITURAS = 200;
  long soma = 0;
  long media = 0;
  int leitura = analogRead(A5);
  
  for (int i=0;i < LEITURAS; i++){ soma += leitura; }
  
  media = soma / LEITURAS;
  
  Serial.println(media);
  delay(100);
}




Abaixo está o código que foi mostrado no vídeo. Mas quem for tentar reproduzir, é necessário fazer vários testes, já que eventualmente é possível que falhas ocorram, portanto, essa solução ainda não é 100% confiável, mas ainda sim serve como base para algumas aplicações. 


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

char getTecla(){
  const int LEITURAS = 300;
  long soma = 0;
  long media = 0;
  int maior = 0;
  int menor = 1023;
  
  for (int i = 0; i < LEITURAS; i++) { 
    int leitura = analogRead(A5);                //PINO ANALOGICO A5. MUDAR AQUI
    if (leitura <= 368) { soma=0; break; }
    
    menor = (menor > leitura) ? leitura : menor;
    maior = (maior < leitura) ? leitura : maior;
    soma += leitura;
    
    if ((maior-menor) >= 4){ soma=0; break; }
  }
    
  
  
  media = soma / LEITURAS;
  
  char c = ' ';
  if (media <= 1023 && media >= 971) {c = '1'; }
  if (media <= 970 && media >= 886)  {c = '2'; }
  if (media <= 885 && media >= 814)  {c = '3'; }
  if (media <= 813 && media >= 739)  {c = 'A'; }
  if (media <= 738 && media >= 673)  {c = '4'; }
  if (media <= 672 && media >= 631)  {c = '5'; }
  if (media <= 630 && media >= 595)  {c = '6'; }
  if (media <= 594 && media >= 552)  {c = 'B'; }
  if (media <= 551 && media >= 513)  {c = '7'; }
  if (media <= 512 && media >= 489)  {c = '8'; }
  if (media <= 488 && media >= 466)  {c = '9'; }
  if (media <= 465 && media >= 438)  {c = 'C'; }
  if (media <= 437 && media >= 413)  {c = '*'; }
  if (media <= 412 && media >= 398)  {c = '0'; }
  if (media <= 397 && media >= 383)  {c = '#'; }
  if (media <= 382 && media >= 369)  {c = 'D'; }
  
  
  //somente para testes, retirar ao ser usado
  if (c != ' '){
    Serial.print(media);
    Serial.print(" - ");
    Serial.print(maior);
    Serial.print(" - ");
    Serial.print(menor);
    Serial.print(" - ");
    Serial.print(maior-menor);
    Serial.print(" - ");
  }
  
  return c;
}

void loop() {
  
  char c = getTecla();
  if (c != ' '){
     Serial.println(c);
     delay(150);
  }
}


sábado, 25 de abril de 2015

Sabão Caseiro com óleo usado

Sabão Caseiro com soda em Escamas


Sabão em pó feito a partir do sabão caseiro


Sabão caseiro com soda Liquida








Veja também - Corda feita com sacolas plásticas


Veja também - Isca para Pacu, Tambacu e tambaqui

segunda-feira, 20 de abril de 2015

Arduino - Database com SD Card + Ethernet Shield

Nesse vídeo mostro um exemplo de como criar um banco de dados simples com o Arduino, utilizando Ethernet Shield com SD Card, utilizando a biblioteca EDB (Extended Database Library). os arquivos html são salvos no cartão de memória. 

 Os dados são retornados para o browser através de javascript no formato JSON.



Baixar a biblioteca EDB

https://code.google.com/p/arduino-edb/downloads/list

Depois de instalada a biblioteca acima, é preciso corrigir um bug que existe no código-fonte da biblioteca. abra o arquivo EDB.cpp e modifique a seguinte função, incluindo a linha sinalizada pelo +:

EDB_Status EDB::open(unsigned long head_ptr)
{
EDB_head_ptr = head_ptr;
+ EDB_table_ptr = sizeof(EDB_Header) + EDB_head_ptr;
readHead();
return EDB_OK;
}


modifique também a parte onde está

#include "WProgram.h"
#include <EDB.h>

para

#include "Arduino.h"
#include <EDB.h>



Salve os arquivos HTML abaixo na raiz do cartão de memória


arquivo aut.htm

HTTP/1.1 401 Authorization Required
WWW-Authenticate: Basic realm="Area Restrita"
Content-Type: text/html
Connnection: close
 
<!DOCTYPE HTML>\n
<html><head><title>Error</title>
</head><body><h1>401 Acesso nao autorizado</h1></body></html>



arquivo cab.htm

HTTP/1.1 200 OK
Content-Type: text/html
Connection: keep-alive


arquivo logoff.htm:

HTTP/1.1 401 Authorization Required
Content-Type: text/html
Connnection: close

<!DOCTYPE HTML>
<html><head><title>Logoff</title>
</head><body><h1>Você não está mais conectado</h1></body></html>



arquivo plist.htm:

<!DOCTYPE html>
<html>
<head>
  <style type="text/css">
  tr, td {
    border-bottom: 1px solid black;
padding: 5px;
margin: 0px;
  }
  label{
position:absolute;
left:19px;
margin-right:5px;
  }
  body{font-family: arial}
  h1 {color: #FF0000;}
  </style>
  <script src="/js_proc_list"></script>
  <script>
function init(){ 
 if (document.URL.indexOf("insert_proc") > -1){ window.location = '/'; }
 if (document.URL.indexOf("del_proc") > -1)   { window.location = '/';}
 var obj = JSON.parse(json_proc);
 var html = '<table>';
 for(var i=0; i<obj.processos.length;i++){
        html += '<tr>' + 
 '<td>' + obj.processos[i].id_proc + '</td>' + 
 '<td>' + obj.processos[i].proc + '</td>' + 
 '<td>' + '<a href="del_proc?p='+obj.processos[i].id_proc+'" onclick=\"return confirm(\'Deseja realmente excluir?\');\">Excluir</a></td>' + 
 '</tr>';
 }
 html += '</table>';
 document.getElementById("lproc").innerHTML = html;
}
  </script>
</head>
<body onload="init();">
  <div><a href="/">Home</a> | <a href="/logoff" onclick="return confirm('Deseja realmente sair?');">Logoff</a></div>
  <br>
  <form action="/insert_proc" method="GET">
    Nome Processo:
    <input type="text" name="p" maxlength="15" id="p"/><input type="submit" value="incluir">
  </form>
  <br>
  <div id="lproc"></div>
</body>
</html>


código-fonte (sketch)


/**********************************************************************************
************************************BIBLIOTECAS************************************
**********************************************************************************/
#include <SPI.h>
#include <Ethernet.h>
#include <SD.h>
#include <EDB.h>
/**********************************************************************************
********************************FIM BIBLIOTECAS************************************
**********************************************************************************/

/****************************************************************************************
 ****************************DECLARACAO DAS TABELAS INICIO*******************************
 ****************************************************************************************/
#define TABLE_SIZE_PROC 512
#define TABLE_NAME_PROC "p.db"

EDB  edb_proc(&writer_proc, &reader_proc);

/******************STRUCTS DAS TABELAS***************************************************/
struct Struct_proc {
  int id_proc;
  char proc[15];
} struct_proc;

/******************INICIALIZA BANCO******************************************************/

void iniciar_banco_dados(){
  char * f = TABLE_NAME_PROC;
  File file_proc;
  if (SD.exists(f)){
    file_proc = SD.open(f, FILE_WRITE);
    edb_proc.open(0);
  } else {
    file_proc = SD.open(f, FILE_WRITE);
    edb_proc.create(0, TABLE_SIZE_PROC, sizeof(struct_proc));
  }
  file_proc.close();
}

/******************WRITER/READER PROC******************************************************/
void writer_proc (unsigned long address, byte data) {
  File file_proc;
  file_proc = SD.open(TABLE_NAME_PROC, FILE_WRITE);
  file_proc.seek(address); 
  file_proc.write(data); 
  file_proc.flush();
  file_proc.close();
}

byte reader_proc (unsigned long address) { 
  File file_proc;
  file_proc = SD.open(TABLE_NAME_PROC, FILE_WRITE);
  file_proc.seek(address); 
  byte b = file_proc.read();   
  file_proc.close();
  return    b;
}

/*********operacoes de inclusao/alteracao/leitura/exclusão processos******************/
void edb_insert_proc(int id_proc, char * proc) {
  struct_proc.id_proc = id_proc; 
  strcpy( struct_proc.proc, proc );
  edb_proc.appendRec(EDB_REC struct_proc);
}

void edb_delete_proc(int id){
  for (int recno=1; recno <= edb_proc.count(); recno++) {
    edb_proc.readRec(recno, EDB_REC struct_proc);
    if (struct_proc.id_proc == id) {
      edb_proc.deleteRec(recno);
      break;
    }
  }
}

void edb_update_proc(int id_proc, char * proc){ 
  struct_proc.id_proc   = id_proc; 
  strcpy( struct_proc.proc, proc );
  edb_proc.updateRec(id_proc, EDB_REC struct_proc);
}

void edb_read_proc(unsigned long recno_proc){
  edb_proc.readRec(recno_proc, EDB_REC struct_proc);
}

int edb_max_proc_id() {
  int max=0;
  Struct_proc s;
  for (int recno=1; recno <= edb_proc.count(); recno++) {
    edb_proc.readRec(recno, EDB_REC s);
    
    if (s.id_proc > max) { max = s.id_proc; }
  }
  return max;
}


/****************************************************************************************
 ****************************DECLARACAO DAS TABELAS FIM**********************************
 ****************************************************************************************/

 /****************************************************************************************
 ****************************SD CARD INICIO***********************************************
 ****************************************************************************************/

boolean iniciar_sd_card() {
  pinMode(10, OUTPUT);
  digitalWrite(10, HIGH);
   
  if (!SD.begin(4)) { return false; }
   
  return true;
}

/****************************************************************************************
 ****************************SD CARD FIM**************************************************
 ****************************************************************************************/


/**********************************************************************************
*************************ROTINAS USUARIO E SENHA***********************************
***********************************************************************************/

boolean validar_usuario(char * linebuf) {
  /*
  nesse exemplo o usuario e senha estão definidos dentro do código fonte.
  mas o usuário e senha poderiam ser autenticados de diversas maneiras,
  lendo os dados de um servidor web, arquivo texto, etc, bastando apenas atribuir
  o valor lido para a variável usuario_senha. 
  */
  
  char usuario_senha[] = "admin:admin";
  int t = strlen(usuario_senha);
  
  int tamanhoEnc = (((t-1) / 3) + 1) * 4;   //tamanho da string codificada
  char out[tamanhoEnc];
  base64_encode(out, usuario_senha, t+1 );
  
  //---desconta é usado pra eliminar os caracteres '='
  int desconta = 0;
  if ((t%3) == 1) { desconta = 2; }
  if ((t%3) == 2) { desconta = 1; }
  
  char out2[tamanhoEnc-desconta];
  
  byte i;
  for (i=0; i<(tamanhoEnc-desconta);i++){ out2[i] = out[i]; }
  out2[i] = '\0';
  
  return ( strstr(linebuf, out2)>0 );
}

/**********************************************************************************
*************************FIM ROTINA USUARIO E SENHA********************************
***********************************************************************************/

/**********************************************************************************
***********************************PAGINAS HTML************************************
***********************************************************************************/
EthernetServer * server;

void iniciar_ethernet(){
  byte ip[4]      = {192,168,200,188};
  //byte gateway[4] = {192,168,200,254};
  //byte subnet[4]  = {255,255,255,0};
  byte mac[6]     = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};
  int  porta      = 80;

  server = new EthernetServer(porta);

  //Ethernet.begin(mac, ip, gateway, subnet);         //caso necessario gateway utilizar essa linha
  Ethernet.begin(mac, ip);
  server->begin();
}

void write_from_file(EthernetClient &client, char * file_name){
  File webFile = SD.open(file_name);
  if (webFile) {
    while(webFile.available()) {
      client.write(webFile.read()); 
    }
    webFile.close();
  }
}

void html_cab_200_ok(EthernetClient &client){
  client.println(F("HTTP/1.1 200 OK\n"
                   "Content-Type: text/html\n"
                   "Connection: keep-alive\n\n"));
}

void html_logoff(EthernetClient &client){
  write_from_file(client, "logoff.htm");
}

void html_autenticar(EthernetClient &client) {
  write_from_file(client, "aut.htm");
}

void html_proc_list(EthernetClient &client) {
  html_cab_200_ok(client);
  write_from_file(client, "plist.htm");
}

void js_proc_list(EthernetClient &client){
  //cabecalho para javascript
  client.println(F("HTTP/1.1 200 OK\n"
                   "Content-Type: text/javascript\n"
                   "Connection: keep-alive\n\n"));
                              
  client.print("var json_proc=\'{\"processos\":[");  
  char virgula = ' ';
  for (int recno = 1; recno <= edb_proc.count(); recno++) {
    edb_proc.readRec(recno, EDB_REC struct_proc);
    
    client.print(virgula);
    client.print("{\"id_proc\":\"");
    client.print(struct_proc.id_proc);
    client.print("\", \"proc\":\"");
    client.print(struct_proc.proc);
    client.print("\"}");
    
    virgula = ',';
  }  
  
  client.print("]}\';");  
}

void delete_proc(char * linebuf) {  
  char * p = strstr(linebuf, "p=");  // /GET ?p=123
  char r[5] = {'\0'};
  
  if (p) {
    byte i=0;
    while (p[i+2] >= '0' && p[i+2] <= '9') {
      r[i] = p[i+2];
      i++;
      if (i==4) {break;}
    }
    r[i]='\0';
  }

  if (r[0] >= 48 && r[0] <= 57) {  //48->0  57->9
    edb_delete_proc(atoi(r));  //apaga o registro
  }  
}

void insert_proc(char * linebuf) {  
  char * p = strstr(linebuf, "p=");  // /GET ?p=123
  char r[16] = {'\0'};
  
  if (p) {
    byte i=0;
    while (p[i+2] != ' ') {
      r[i] = (p[i+2] == '+') ? r[i] = ' ' : r[i] = p[i+2];
      i++;
      if (i==15) {break;}
    }
    r[i]='\0';
  }

  edb_insert_proc(edb_max_proc_id()+1, r);  //inclui registro
}

void exec_ethernet(){
  EthernetClient client = server->available();
  if (client) {
    char linebuf[80];
    memset(linebuf, 0, sizeof(linebuf));
    
    int     charCount          = 0;
    boolean autenticado        = false;
    boolean currentLineIsBlank = true;
    boolean logoff             = false;
    boolean jsProcList         = false;
    boolean listProc           = false;
    
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();
        
        linebuf[charCount] = c;
        
        if (charCount<sizeof(linebuf)-1) { charCount++; }
        Serial.write(c);
        
        if (c == '\n' && currentLineIsBlank) {
          if (autenticado && !logoff ) {
            if(jsProcList) { js_proc_list(client);   } 
            if(listProc)   { html_proc_list(client); }
          } else {
            logoff ? html_logoff(client) : html_autenticar(client);
          }
          break;
        }
        if (c == '\n') { 
          currentLineIsBlank = true;               
          
          if (strstr(linebuf, "Authorization: Basic")>0 ) { if ( validar_usuario(linebuf) )   {  autenticado = true; } }
          if (strstr(linebuf, "GET /logoff"         )>0 ) { logoff      = true; }
          if (strstr(linebuf, "GET / "              )>0 ) { listProc    = true; }
          if (strstr(linebuf, "GET /js_proc_list"   )>0 ) { jsProcList  = true; }
          if (strstr(linebuf, "GET /del_proc"       )>0 ) { listProc    = true; delete_proc(linebuf); }
          if (strstr(linebuf, "GET /insert_proc"    )>0 ) { listProc    = true; insert_proc(linebuf); }
          
          memset(linebuf, 0, sizeof(linebuf));
          charCount = 0;
        } else if (c != '\r') {
          currentLineIsBlank = false;    // you've gotten a character on the current line
        }
      }
    }
    
    delay(1);           // give the web browser time to receive the data
    client.stop();      // close the connection:
  }
}
/**********************************************************************************
**************************************** FIM PAGINAS HTML**************************
***********************************************************************************/


/**********************************************************************************
*************************BASE 64 CODE/DECODE DO USUARIO E SENHA********************
***********************************************************************************/

void a3_to_a4(unsigned char * a4, unsigned char * a3);
void a4_to_a3(unsigned char * a3, unsigned char * a4);
unsigned char b64_lookup(char c);

int base64_encode(char *output, char *input, int inputLen) {
  const char b64_alphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
  int i=0, j=0, encLen=0;
  unsigned char a3[3], a4[4];

  while(inputLen--) {
    a3[i++] = *(input++);
    if(i == 3) {
      a3_to_a4(a4, a3);
      for(i=0; i<4; i++) { output[encLen++] = b64_alphabet[a4[i]]; }
      i = 0;
    }
  }

  if (i) {
    for(j = i; j < 3; j++)     { a3[j] = '\0';                           }
    a3_to_a4(a4, a3);
    for(j = 0; j < i + 1; j++) { output[encLen++] = b64_alphabet[a4[j]]; }
    while((i++ < 3))           { output[encLen++] = '=';                 }
  }
  output[encLen] = '\0';
  return encLen;
}

void a3_to_a4(unsigned char * a4, unsigned char * a3) {
  a4[0] = (a3[0]  & 0xfc) >> 2;
  a4[1] = ((a3[0] & 0x03) << 4) + ((a3[1] & 0xf0) >> 4);
  a4[2] = ((a3[1] & 0x0f) << 2) + ((a3[2] & 0xc0) >> 6);
  a4[3] = (a3[2] & 0x3f);
}

unsigned char b64_lookup(char c) {
  if(c >='A' && c <='Z') return c - 'A';
  if(c >='a' && c <='z') return c - 71;
  if(c >='0' && c <='9') return c + 4;
  if(c == '+') return 62;
  if(c == '/') return 63;
  return -1;
}

/**********************************************************************************
*************************FIM BASE 64 CODE/DECODE DO USUARIO E SENHA****************
***********************************************************************************/

/**********************************************************************************
**************************************** VOID / LOOP ******************************
***********************************************************************************/

void setup() {
  Serial.begin(9600);
  iniciar_sd_card();
  iniciar_banco_dados();
  iniciar_ethernet();
}

void loop() {
  exec_ethernet();
}

/**********************************************************************************
*************************************FIM VOID / LOOP*******************************
***********************************************************************************/