ciar de algum ponto, e o importante é isso: ir em frente.
Primeiro, respondendo suas perguntas, na sequência que vc as colocou:
1) olhei na Internet o seu modelo de Arduino UNO "Lafvin". Ele é um Arduino UNO convencional, e pode ser utilizado como qualquer outro UNO. Então vc não precisa se referir a ele especificamente por "Lafvin". Chame-o apenas de "UNO".
2) os "comandos" "sei()" e "cli()" a que vc se refere, nós chamamos tecnicamente de "statements", e nada mais são do que funções para controle da Interrupção Geral do Processador "AVR" (o Processador do Arduino UNO) , e que são equivalentes respectivamente às funções "interrupts()" e "noInterrupts()" do Arduino. Assim dê uma olhada no site do Arduino sobre estas duas funções. Os links são estes dois: "interrupts" e "noInterrupts". O site estará em inglês, então use o tradutor do Google conforme preferir.
Estes dois "comandos", só devem ser utilizados se vc tiver uma boa experiência com Programação (não precisa ser do Arduino). Isto porque, eles tem consequências diversas para o funcionamento adequado do Sistema, e se utilizados de forma inadequada, seu Sistema poderá ter efeitos colaterais estranhos e que poderão até confundir vc.
E para o que vc quer fazer, não é necessário usar estes dois "comandos", como mostrarei adiante (no código que implementei).
3) o fato dos dois "comandos" não aparecerem "grafados" como vc diz, é irrelevante. Vou explicar. Os "comandos" que aparecem "grafados", aparecem assim porque eles estão descritos em um arquivo texto em alguma Biblioteca do Arduino, e estes arquivos sempre tem o nome "keywords.txt". Isto é usado apenas para ressaltar a visualização dos "comandos" no Editor do Arduino, e nada mais. Ou seja, não tem efeito no resultado da compilação do código. Então não se preocupe com isso. Além disso, o "sei" e o "cli" não deveriam mesmo aparecerem "grafados", pois são "primitivas" do Compilador AVR, e não exatamente "comandos", e de fato não deveriam estar em nenhum arquivo "keywords.txt" (e se estiverem, a pessoa que fez isso se equivocou, pois não domina a fundo o ambiente).
4) os valores e informações não aparecem adequadamente no Display LCD, porque simplesmente os "comandos" (ou "statements"), estão sendo usados de forma totalmente equivocada no seu código. A forma de se usar isto, é simples na plataforma Arduino. Então vc precisa "estudar" um pouco mais sobre isso, e certamente vai entender como usá-los (no código que estou postando mais adiante, vc poderá ver como isso é feito, e então usar como exemplo).
5) como vc está bem "verde" em Programação, primeiro vc precisa fazer o básico no seu código, e isto nada mais é do que medir a vazão em Litros/minuto de forma adequada e confiável, e então depois disso fazer a parte um pouco mais elaborada que vc descreveu (usando dois Sensores de Fluxo "yf-s201c" e um fim-de-curso). Veja: se vc medir adequadamente o Fluxo em um Sensor, então conseguirá medir em dois (ou a quantidade de sensores que vc quiser). Então bastará fazer os cálculos (algo muito simples em Programação) no momento adequado (conforme o seu fim-de-curso). E exibir os resultados no Display, será da mesma forma de sempre. Mas há Técnicas de Programação, que vc certamente terá que ficar mais acostumado. O que posso te dizer sobre isso, é que as pessoas sempre complicam e são muito desorganizadas, e isto é a chave pra tudo dar errado em Programação. Programação, exige que vc seja organizado, é imperativo. Se vc não for assim, então em algum momento vai ter problemas com seu Sistema, e provavelmente eles serão difíceis de resolver (não vou explicar os motivos disto neste momento).
Então pra dar um empurrão, estou postando um código para o Sistema que vc descreveu no seu código original. Veja: não é para o Sistema com dois sensores, pois quero te mostrar como se faz a coisa mais simples primeiro. O pessoal que me acompanha aqui, sabe que os Sistemas que posto aqui são bastante completos em termos de explicação e documentação, e os códigos são totalmente comentados de forma funcional. E 99% das vezes, eu posto também uma simulação do Sistema (usando o Proteus, devido à popularidade do mesmo).
Então o que está sendo feito neste código? Ele simplesmente mede o Fluxo de um Sensor (e nem precisa do "sei" e do "cli"), e exibe isto no Display, e após um minuto (ou 60 amostras), ele calcula a Média da Vazão. Ou seja, exatamente o que vc tentou fazer no seu código original. No entanto vc vai perceber, que o código que estou postando, é completamente diferente do seu original. Então analise o mesmo com atenção, sem pressa, e com a intenção de aprender. No código, estou usando técnicas clássicas para obter os resultados esperados. Assim se vc conseguir aprender, terá avançado tremendamente, e poderá seguir em frente com ainda mais confiança.
Implementei também a Simulação do seu Sistema usando o Proteus, e o Hardware equivalente, vc pode ver na figura a seguir:
(clique na figura para "zoom")
Se ficar estranho pra vc o Hardware na figura anterior, não se preocupe, pois realmente isso vai ocorrer se vc não está familiarizado com Hardware, com Eletrônica, e com o próprio Proteus. O importante é não achar que é algo transcendental ou do Egito antigo.
O resultado da Simulação vc pode ver nas figuras a seguir, onde "printei" a tela do Proteus em três momentos diferentes: 4 segundos após iniciar a execução do código, depois após 32 segundos, e finalmente após 60 segundos (quando a média é calculada e exibida). Após a exibição da Média da Vazão, o Sistema reinicia todo o processo de medição, e isto se repete indefinidamente. Veja os resultados nas figuras:
(clique nas figuras para "zoom")
O código, vc pode usar diretamente no seu Hardware para verificar o resultado. Apenas atente que o LCD I2C usado no código e no Hardware, tem a "pinagem" padrão desses módulos comercializados na Internet, e que está especificado na linha 48 no código, conforme vc pode ver na figura a seguir:
(clique na figura para "zoom")
Embora esta questão da "pinagem" do LCD I2C estivesse muito confusa (e equivocada) no seu código original, eu assumi que vc tem um módulo e Display I2C padrões, e a "pinagem" que usei corresponde a isso. Mas caso seja diferente (acho pouco provável), informe aqui, que tratarei da melhor forma que eu puder.
O código está aqui: "Fluxo_Agua_02.zip"
Como eu disse, vc pode usar este código diretamente no seu Sistema, pois eu segui as definições e pinagens descritas no seu código original.
E no arquivo zipado, vc também encontrará os arquivos para Simulação no Proteus, caso deseje fazer a Simulação (lá vc pode variar a vazão, através de um Potenciômetro que altera a taxa de pulsos de forma equivalente ao Sensor "real", e pode até desligar o Fluxo através de uma chave equivalente a um "Registro" hidráulico).
Espero ter ajudado.
Abrçs
Elcids…
Adicionado por Elcids Chagas ao 23:01 em 31 março 2020
do colocar umas frescuras como uma pagina html para troca de ip
eu tenho os dois codigos e gostaria de saber como faço eles rodarem juntos... alguem poderia me ajudar?
Código do DMX
#include <SPI.h> // needed for Arduino versions later than 0018#include <Ethernet.h>#include <EthernetUdp.h> #include <lib_dmx.h>
#define DMX512 (0) // (250 kbaud - 2 to 512 channels) Standard USITT DMX-512#define DMX1024 (1) // (500 kbaud - 2 to 1024 channels) Completely non standard - TESTED ok#define DMX2048 (2) // (1000 kbaud - 2 to 2048 channels) called by manufacturers DMX1000K, DMX 4x or DMX 1M ???
//TO EDIT:// the next two variables are set when a packet is receivedbyte destination_Ip[]= { 255,255,255,255 }; // the ip to send data, 255,255,255,255 is broadcast sending// art net parametersunsigned int localPort = 6454; // artnet UDP port is by default 6454const int DMX_Universe=15;//universe is from 0 to 15, subnet is not usedconst int number_of_channels=512; //512 for 512 channels, MAX=512
//HARDWAREbyte mac[] = { 144, 162, 218, 00, 16, 96 };//the mac adress of ethernet shield or uno shield boardbyte ip[] = { 192,168,1,118 };// the IP adress of your device, that should be in same universe of the network you are using, here: 192.168.1.x
//ART-NET variableschar ArtNetHead[8]="Art-Net";//sprintf((char *)node->id, "Art-Net\0"); algum erro aqui ?????????????????????
const int art_net_header_size=17;
short OpOutput= 0x5000 ;//output
byte buffer_dmx[number_of_channels]; //buffer used for DMX data
EthernetUDP Udp;
//Artnet PACKETbyte ArtDmxBuffer[(art_net_header_size+number_of_channels)+8+1];
void setup() {
//initialise artnet header construct_arnet_packet(); // démarrage ethernet et serveur UDP Ethernet.begin(mac,ip); Udp.begin(localPort); ArduinoDmx0.set_control_pin(11); // Arduino output pin for MAX485 input/output control (connect to MAX485 pins 2-3) ArduinoDmx0.set_rx_address(1); // set rx0 dmx start address ArduinoDmx0.set_rx_channels(512); // number of rx channels ArduinoDmx0.init_rx(DMX512); // starts universe 0 as rx, NEW Parameter DMX mode}
void loop() { check_arduino_inputs(); construct_arnet_packet(); Udp.beginPacket(destination_Ip, localPort); Udp.write(ArtDmxBuffer,(art_net_header_size+number_of_channels+1)); // was Udp.sendPacket Udp.endPacket(); delay(40);}
void check_arduino_inputs(){ //data from arduino aquisition
for(int i=0;i<512;i++)//reads the 6 analogic inputs and set the data from 1023 steps to 255 steps (dmx) { buffer_dmx[i]= ArduinoDmx0.RxBuffer[i]; }}
void construct_arnet_packet(){ //preparation pour tests for (int i=0;i<513;i++) { ArtDmxBuffer[i]=ArtNetHead[i]; }
//Operator code low byte first ArtDmxBuffer[8]=OpOutput; ArtDmxBuffer[9]= OpOutput >> 8; //protocole ArtDmxBuffer[10]=0; ArtDmxBuffer[11]=14; //sequence ArtDmxBuffer[12]=0; //physical ArtDmxBuffer[13] = 0; // universe ArtDmxBuffer[14]= DMX_Universe;//or 0 ArtDmxBuffer[15]= DMX_Universe>> 8; //data length ArtDmxBuffer[16] = number_of_channels>> 8; ArtDmxBuffer[17] = number_of_channels; for (int t= 0;t<number_of_channels;t++) { ArtDmxBuffer[t+art_net_header_size+1]=buffer_dmx[t]; } }
Codigo da Configuração WEB
#include <SPI.h>#include <Ethernet.h>#include <TextFinder.h>#include <EEPROM.h>#include <avr/wdt.h>
byte IP1 = 192;//the first part of the IP-addressbyte IP2 = 168; //the second part of the IP-addressbyte IP3 = 14; //the thirth part of the IP-addressbyte IP4 = 85; //the fourth part of the IP-addressbyte GW1 = 192; //the first part of the GATEWAYbyte GW2 = 168; //the second part of the GATEWAYbyte GW3 = 14; //the thirth part of the GATEWAYbyte GW4 = 2; //the fourth part of the GATEWAYbyte SUB1 = 255; //first part of the SUBNETMASKbyte SUB2 = 255; //the second part of the SUBNETMASKbyte SUB3 = 255; //the thirth part of the SUBNETMASKbyte SUB4 = 0; //the fourth part of the SUBNETMASKbyte SET = 0;
//seting up the EthernetShieldbyte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };byte ip[] = {IP1,IP2,IP3,IP4};byte gateway[] = {GW1,GW2,GW3,GW4};byte subnet[] = {SUB1,SUB2,SUB3,SUB4};EthernetServer server(80);
const byte ID = 0x95; //used to identify if valid data in EEPROM the "know" bit, // if this is written in EEPROM the sketch has ran before// We use this, so that the very first time you'll run this sketch it will use// the values written above. // defining which EEPROM address we are using for what dataconst byte ID_ADDR = 0; //the EEPROM adress used to store the ID (to check if sketch already has ran)const byte IP_ADDR1 = 1; //the EEPROM adress used to store the first part of the IP-addressconst byte IP_ADDR2 = 2; //the EEPROM adress used to store the second part of the IP-addressconst byte IP_ADDR3 = 3; //the EEPROM adress used to store the thirth part of the IP-addressconst byte IP_ADDR4 = 4; //the EEPROM adress used to store the fourth part of the IP-addressconst byte GW_ADDR1 = 5; //the EEPROM adress used to store the first part of the GATEWAYconst byte GW_ADDR2 = 6; //the EEPROM adress used to store the second part of the GATEWAYconst byte GW_ADDR3 = 7; //the EEPROM adress used to store the thirth part of the GATEWAYconst byte GW_ADDR4 = 8; //the EEPROM adress used to store the fourth part of the GATEWAYconst byte SUB_ADDR1 = 9; //the EEPROM adress used to store the first part of the SUBNETMASKconst byte SUB_ADDR2 = 10; //the EEPROM adress used to store the second part of the SUBNETMASKconst byte SUB_ADDR3 = 11; //the EEPROM adress used to store the thirth part of the SUBNETMASKconst byte SUB_ADDR4 = 12; //the EEPROM adress used to store the fourth part of the SUBNETMASKbyte ip_addr[] = { IP_ADDR1, IP_ADDR2, IP_ADDR3, IP_ADDR4};byte gw_addr[] = { GW_ADDR1, GW_ADDR2, GW_ADDR3, GW_ADDR4};byte sub_addr[] = { SUB_ADDR1, SUB_ADDR2, SUB_ADDR3, SUB_ADDR4};
void setup(){ Serial.begin(9600); ShieldSetup (); //Setup the Ethernet shield server.begin(); //starting the server Serial.print("ready on ip: "); Serial.print(IP1,DEC); Serial.print("."); Serial.print(IP2,DEC); Serial.print("."); Serial.print(IP3,DEC); Serial.print("."); Serial.println(IP4,DEC);}
void ShieldSetup(){ int idcheck = EEPROM.read(ID_ADDR); Serial.println(idcheck,DEC); if (idcheck != ID){ //ifcheck id is not the value as const byte ID, //it means this sketch has NOT been used to setup the shield before Ethernet.begin(mac, ip, gateway, subnet); //just use the values written in the beginning of the sketch Serial.println("first time sketch has run"); } if (idcheck == ID){ //if id is the same value as const byte ID, //it means this sketch has been used to setup the shield. //So we will read the values out of EERPOM ans use them //to setup the shield. IP1 = EEPROM.read(IP_ADDR1); IP2 = EEPROM.read(IP_ADDR2); IP3 = EEPROM.read(IP_ADDR3); IP4 = EEPROM.read(IP_ADDR4); GW1 = EEPROM.read(GW_ADDR1); GW2 = EEPROM.read(GW_ADDR2); GW3 = EEPROM.read(GW_ADDR3); GW4 = EEPROM.read(GW_ADDR4); SUB1 = EEPROM.read(SUB_ADDR1); SUB2 = EEPROM.read(SUB_ADDR2); SUB3 = EEPROM.read(SUB_ADDR3); SUB4 = EEPROM.read(SUB_ADDR4); byte ip[] = {IP1,IP2,IP3,IP4}; byte gateway[] = {GW1,GW2,GW3,GW4}; byte subnet[] = {SUB1,SUB2,SUB3,SUB4}; Ethernet.begin(mac, ip, gateway, subnet); Serial.println("NOT the first time sketch has run"); }}
void ShieldValueWrite(){ Serial.println("writing to EEPROM"); for (int i = 0 ; i < 4; i++) { EEPROM.write(ip_addr[i], ip[i]); } for (int i = 0 ; i < 4; i++) { EEPROM.write(gw_addr[i], gateway[i]); } for (int i = 0 ; i < 4; i++) { EEPROM.write(sub_addr[i], subnet[i]); } }
void loop(){ EthernetClient client = server.available(); if (client) { TextFinder finder(client ); while (client.connected()) { if (client.available()) { if( finder.find("GET /") ) { Serial.println("connection has been made"); if (finder.findUntil("SBM", "\n\r")){ Serial.println(); Serial.println("found a submitted form"); SET = finder.getValue(); while(finder.findUntil("DT", "\n\r")){ int val = finder.getValue(); if(val >= 0 && val <= 3) { ip[val] = finder.getValue(); } if(val >= 4 && val <= 7) { subnet[val - 4] = finder.getValue(); } if(val >= 8 && val <= 11) { gateway[val - 8] = finder.getValue(); } } Serial.print("The new IP address is:"); Serial.print(ip[0],DEC); for (int i= 1; i < 4; i++){ Serial.print("."); Serial.print(ip[i],DEC); } Serial.println(); Serial.print("The new Subnet is:"); Serial.print(subnet[0],DEC); for (int i= 1; i < 4; i++){ Serial.print("."); Serial.print(subnet[i],DEC); } Serial.println(); Serial.print("The new gateway is:"); Serial.print(gateway[0],DEC); for (int i= 1; i < 4; i++){ Serial.print("."); Serial.print(gateway[i],DEC); } Serial.println(); ShieldValueWrite(); // writing all the values whitin the form into EEPROM EEPROM.write(ID_ADDR, 0x95); //set ID to the known bit, so when you reset the Arduino is will use the EEPROM values Serial.println("all data has been written to EEPROM"); Serial.println("you can now reset the Arduino"); Serial.println("and use the new ip in your browser"); // // if al the data has been written to EEPROM we should reset the arduino // for now you'll have to use the hardware reset button } } client.println("HTTP/1.1 200 OK"); client.println("Content-Type: text/html"); client.println(); client.print("<html><body><table><form><input type=\"hidden\" name=\"SBM\" value=\"1\">"); client.print("<tr><td>IP: <input type=\"text\" size=\"1\" maxlength=\"3\" name=\"DT0\" value=\""); client.print(IP1,DEC); client.print("\">.<input type=\"text\" size=\"1\" maxlength=\"3\" name=\"DT1\" value=\""); client.print(IP2,DEC); client.print("\">.<input type=\"text\" size=\"1\" maxlength=\"3\" name=\"DT2\" value=\""); client.print(IP3,DEC); client.print("\">.<input type=\"text\" size=\"1\" maxlength=\"3\" name=\"DT3\" value=\""); client.print(IP4,DEC); client.print("\"></td></tr><tr><td>MASK: <input type=\"text\" size=\"1\" maxlength=\"3\" name=\"DT4\" value=\""); client.print(subnet[0],DEC); client.print("\">.<input type=\"text\" size=\"1\" maxlength=\"3\" name=\"DT5\" value=\""); client.print(subnet[1],DEC); client.print("\">.<input type=\"text\" size=\"1\" maxlength=\"3\" name=\"DT6\" value=\""); client.print(subnet[2],DEC); client.print("\">.<input type=\"text\" size=\"1\" maxlength=\"3\" name=\"DT7\" value=\""); client.print(subnet[3],DEC); client.print("\"></td></tr><tr><td>GW: <input type=\"text\" size=\"1\" maxlength=\"3\" name=\"DT8\" value=\""); client.print(gateway[0],DEC); client.print("\">.<input type=\"text\" size=\"1\" maxlength=\"3\" name=\"DT9\" value=\""); client.print(gateway[1],DEC); client.print("\">.<input type=\"text\" size=\"1\" maxlength=\"3\" name=\"DT10\" value=\""); client.print(gateway[2],DEC); client.print("\">.<input type=\"text\" size=\"1\" maxlength=\"3\" name=\"DT11\" value=\""); client.print(gateway[3],DEC); client.print("\"></td></tr><tr><td><input type=\"submit\" value=\"SUBMIT\"></td></tr>"); client.print("</form></table></body></html>"); client.print("free test SRAM = "); client.print(availableMemory()); client.print(" / SRAM used = "); client.print(2048-availableMemory()); break; } } delay(1); client.stop(); }}
int availableMemory(){ int size = 2048; byte *buf; while ((buf = (byte *) malloc(--size)) == NULL); free(buf); return size;}…
Adicionado por Deives Bender ao 20:57 em 11 fevereiro 2014
l dúvida é em relação ao menu do LCD onde pretendo ter na primeira tela após ser acionado por um botão "bverde" uma mensagem com o nome da máquina passando então 1 segundo irá mostrar a quantidade a ser envasada. A quantidade será o valor digitado no Keypad;
- Após o valor ser digitado pelo keypad uma segunda tela é mostrada, nessa tela será contada a quantidade de envasada e pressionando o "bamarelo" muda a tela para a terceira tela onde irá mostrar o nível do tanque de armazenamento, pressionando o "bamarelo" novamente ele volta para a segunda tela, ou seja o "bamarelo" irá funcionar como um botão de opões que transita entre essas duas telas;- Usando um decrementador quero que o mesmo decremente o valor digitado na tela 1 mostrando a mensagem de que o Lote esta pronto e que se deve inserir um novo valor;- Um terceiro botão "bvermelho" seria o botão de emergência, ou seja se pressionado a máquina trava.- Todo esse programa foi baseado em exemplos e projetos que encontrei aqui no fórum e em outros sites.
Como devo organizar os botões para agirem desta maneira ? Pois eles estão executando as ações que defini mais não da maneira que descrevi acima.
Segue o Programa:
//========================================================================#include <Keypad.h>#include <LiquidCrystal.h> LiquidCrystal lcd(22,23,24,25,26,27); // DECLARAÇÃO DOS PINOS DO LCD NO ARDUINO// DEFINIÇÃO DOS BOTÕES - VERDE. VERMELHO, AMARELO#define bverde A1 // Os pinos analógicos podem ser#define bamarelo A2 // usados como digitais, bastando#define bvermelho A3 // referenciá-los por A0, A1..#define bDown A4#define bverde0 90 // Valor de referência que a#define bamarelo0 91 // função CheckButton() passa#define bvermelho0 92 // indicando que um botão foi#define bDown0 93 // soltoboolean averde, aamarelo, avermelho, aDown; // Grava o ultimo valor lidos nos botões.// Utilizado pela função Checkbutton p/ identificar quando há uma alteração no estado do pino dos botões// DEFINIÇÃO DOS PINOS E VALORES PARA O SENSOR, ESTEIRA E BOMBAint contador = 0; int Sensor = 0; int sensorPin = A0; int MotorEsteira = 11;int MotorBomb= 12;int EstadoMotor=0;int EstadoSensor=1;int LED1=8;int LED2=9;int LED3=10;int LED4=2;int buzzer=7;int variavel; // VARIAVEL A SER ALTERADA PELO MENUchar state=1; // VARIÁVEL QUE GUARDA POSIÇÃO ATUAL DO MENUint dec=-1;int i=0;const byte LIN = 4; // TECLADO POSSUI 4 LINHASconst byte COL = 3; //TECLADO POSSUI 3 COLUNASchar keys[LIN][COL] = { {//MATRIZ CORRESPONDENTE AOS CARACTERES DO KEYPAD '1','2','3' }, {'4','5','6' },{'7','8','9' },{'*','0','#' }};byte LinPins[LIN] = {28,29,30,31}; //PINOS DO ARDUINO CORRESPONDENTES AS COLUNASbyte ColPins[COL] = {32,33,34}; //E AS LINHAS DA MATRIZKeypad keypad = Keypad( makeKeymap(keys), LinPins, ColPins, LIN, COL );char key = keypad.getKey();void setup(){lcd.begin(16, 2); // Iniciando a biblioteca do LCDSerial.begin(9600); // DEFINIÇÃO DA PORTA SERIALpinMode(bverde, INPUT); // BotõespinMode(bamarelo,INPUT);pinMode(bvermelho, INPUT);pinMode(bDown, INPUT);digitalWrite(bverde, HIGH); // Aciona o pull-up internodigitalWrite(bamarelo,HIGH); // dos botõesdigitalWrite(bvermelho, HIGH);digitalWrite(bDown, HIGH);pinMode(sensorPin, INPUT); //DEFINIR SE A VARIAVEL É ENTRADA(IMPUT) OU SAIDA(OUTPUT) DE DADOSpinMode(MotorEsteira, OUTPUT); pinMode(MotorBomb, OUTPUT);pinMode(EstadoSensor, INPUT);pinMode(LED1, OUTPUT);pinMode(LED2, OUTPUT);pinMode(LED3, OUTPUT);pinMode(LED4, OUTPUT);pinMode(buzzer, OUTPUT);}void loop(){Sensor = digitalRead(sensorPin); // A VARIAVEL SENSOR CORRESPONDE AO sensorPin QUE ESTÁ LIGADO A PORTA ANALÓGICA A0 DO ARDUINif(Sensor == LOW){ digitalWrite(MotorEsteira, HIGH); // SE O SENSOR NÃO ESTIVER ACIONADO O MOTOR DA BOMBA ESTA PARADO E O LED1 ASCESOdigitalWrite(LED1,HIGH); digitalWrite(LED2, LOW);digitalWrite(MotorBomb, LOW);digitalWrite(buzzer, LOW);}if(Sensor == HIGH) { // SE O SENSOR ESTIVER ACIONADO O MOTOR DA ESTEIRA ESTA PARADO E O LED1 APAGAdigitalWrite(MotorEsteira, LOW); // O MOTOR DA BOMBA LIGA E O LED2 ASCENDE E UM TOQUE DE 2 SEGUNDO É digitalWrite(MotorBomb, HIGH); // ACIONADO PELO BUZZER digitalWrite(LED1, LOW);digitalWrite(LED2, HIGH);delay(8000);//ESTE DELAY SERVE PARA A BOMBA JOGAR 200ml DE AGUA NA GARRAFAcontador++;Sensor == !Sensor; //O SINAL DO SENSOR É INVERTIDO PARA A FUNÇAO RETORNAR DE ONDE ESTAVA}EstadoSensor = digitalRead(sensorPin); // O SINAL DO SENSOR É MOSTRADO NO SERIAL MONITOR Serial.println(Sensor);if(EstadoSensor == HIGH){ // A FUNÇAO RETORNA AO ESTADO INICIALdigitalWrite(MotorEsteira, HIGH); digitalWrite(MotorBomb, LOW);digitalWrite(LED1, HIGH);digitalWrite(LED2, LOW);digitalWrite(buzzer,LOW);delay(2000);}switch (state) { // Define checa qual tela atualcase 1: // executado quando na TELA 1switch (CheckButton()) {case bverde:lcd.setCursor(0,0);lcd.print("Maquina Envase");lcd.setCursor(0,2);lcd.print("Eng. Mecatronica");delay(5000);lcd.clear();lcd.setCursor(0,0); lcd.print("Controle Prod.");Set_state(1);break;case bamarelo:lcd.clear(); Set_state(2); // antes de mudar de tela, é necessário limpar obreak; lcd.clear(); Set_state(3); // display com a função lcd.clear()break;lcd.clear(); Set_state(1);break;default: // Caso nenhum botão tenha sido apertado, ela executa a set_stateSet_state(1); // mesmo assim para atualizar o display.}break;case 2: // executado quando na TELA 2switch (CheckButton()) {case bverde: lcd.clear(); Set_state(1);break;case bamarelo: //lcd.clear(); Set_state(3);break;lcd.clear(); Set_state(1);break;lcd.clear(); Set_state(2);break;default:Set_state(2);}break;case 3: // executado quando na TELA 3switch (CheckButton()) {case bverde: lcd.clear(); Set_state(1);case bamarelo:lcd.clear(); Set_state(2);break;lcd.clear(); Set_state(3);break;lcd.clear(); Set_state(1);break;default:Set_state(3);}break;case 4: // executado quando na TELA 4switch (CheckButton()) {case bamarelo:lcd.clear(); Set_state(1);break;default:Set_state(1);}break;default: ;}}// FIM DO LOOPchar CheckButton() { if (averde!=digitalRead(bverde)) { averde=!averde; if (averde) return bverde0; else return bverde;} elseif (aamarelo!=digitalRead(bamarelo)) {aamarelo=!aamarelo;if (aamarelo) return bamarelo0; else return bamarelo;} elseif (avermelho!=digitalRead(bvermelho)) {avermelho=!avermelho;if (avermelho) return bvermelho0; else return bvermelho;} elseif (aDown!=digitalRead(bDown)) {aDown=!aDown;if (aDown) return bDown0; else return bDown;} elsereturn 0;}void PCP() // FUNÇÃO QUE DEFINE A QUANTIDADE DE GARRAFAS A SEREM ENVASADAS NO DIA{char key = keypad.getKey();if (key != NO_KEY){lcd.setCursor(i,2); lcd.print(key);i++;}}void Set_state(char index) {state = index; // Atualiza a variável state para a nova telaswitch (state) { // verifica qual a tela atual e exibe o conteúdo correspondentecase 1: //==================== state 1PCP();break;case 2: //==================== state 2lcd.setCursor(0,0);lcd.print("Qnt. Envasada:");lcd.setCursor(0,1);lcd.print(contador); // mostra os segundos na telalcd.print(" garrafas");delay(20);// if(contador==key){// lcd.setCursor(0,0);// lcd.print("Lote Pronto!");// lcd.setCursor(0,1);// lcd.print("Insira Novo");// }break;case 3: //==================== state 3lcd.setCursor(0,0);lcd.print("Nivel Tanque");lcd.setCursor(1,2);lcd.print("%");break;case 4: //==================== state 4break;default: ;}}…
guinte: tenho vários motores instalados em uma fábrica, estes motores possuem contatos auxiliares de alarme para informar quando um motor entrar em sobrecarga. Gostaria que o Arduíno Mega/Emissor recebesse o sinal (5V) destes contatos e me enviasse uma SMS informando que o motor está desarmado. A idéia básica é a seguinte:No Emissor:Eu recebo o sinal de 5V no pino 22 do arduino mega, por exemplo, recebendo este sinal eu escrevo na serial o valor "A".Eu recebo o sinal de 5V no pino 23 do arduino mega, por exemplo, recebendo este sinal eu escrevo na serial o valor "B". Eassim sucessivamente.No receptor (Arduíno Uno + Shield SIM 900 ICOMSAT 1.1):No receptor eu leio o que está escrito na serial e faço meu comando.Se ler o caracter 'A' na serial, envia SMS "M1 DESARMADO".Se ler o caracter 'B' na serial, envia SMS "M2 DESARMADO".O problemas destes códigos é que fica enviando SMS sem parar.
Vcs poderiam me dar uma luz para este caso? Segue abaixo os códigos:
//Arduino Mega (emissor)
byte contatoM1=22; //define o contato do motor M1byte contatoM2=23; //define o contato do motor M2byte contatoM3=24; //define o contato do motor M3byte contatoM4=25; //define o contato do motor M4byte contatoM5=26; //define o contato do motor M5byte contatoM6=27; //define o contato do motor M6byte contatoM7=28; //define o contato do motor M7byte contatoM8=29; //define o contato do motor M8byte contatoM9=30; //define o contato do motor M9byte contatoM10=31;//define o contato do motor M10byte contatoM11=32; //define o contato do motor M11byte contatoM12=33; //define o contato do motor M12byte contatoM13=34; //define o contato do motor M13byte contatoM14=35; //define o contato do motor M14byte contatoM15=36; //define o contato do motor M15byte contatoM16=37; //define o contato do motor M16byte contatoM17=38;//define o contato do motor M17byte A, B, C, D, E,F, G,H,I,J,L,M,N,O,Q,R,S;boolean enviouA, enviouB,enviouC, enviouD,enviouE, enviouF,enviouG, enviouH,enviouI, enviouJ,enviouL, enviouM,enviouN, enviouO,enviouQ, enviouR,enviouS=false; // flags booleanasbyte tx=1; // define o pino de saída Serial
boolean tempodecorte() { static unsigned long last_interrupt_time = 0; // define o tempo de referencia como zero unsigned long interrupt_time = millis(); // comeca a contagem do tempo if(interrupt_time - last_interrupt_time > 5000) // aplica a condição tempo de contagem maior que 5 s do que o tempo de referencia { last_interrupt_time = interrupt_time; // se a condicao é satisfeita redefine o tempo de referencia como o tempo de contagem return true; // e contabiliza o voto } return false; // se nao, nao contabiliza o voto }
void setup() { Serial.begin(9600); // inicializa o Serial com 9600 bauds pinMode(contatoM1, INPUT); pinMode(contatoM2, INPUT); pinMode(contatoM3, INPUT); pinMode(contatoM4, INPUT); pinMode(contatoM5, INPUT); pinMode(contatoM6, INPUT); pinMode(contatoM7, INPUT); pinMode(contatoM8, INPUT); pinMode(contatoM9, INPUT); pinMode(contatoM10, INPUT); pinMode(contatoM11, INPUT); pinMode(contatoM12, INPUT); pinMode(contatoM13, INPUT); pinMode(contatoM14, INPUT); pinMode(contatoM15, INPUT); pinMode(contatoM16, INPUT); pinMode(contatoM17, INPUT); pinMode(tx,OUTPUT); digitalWrite(tx,HIGH); // "liga" o pino de saída Serial } void loop() { A=digitalRead(contatoM1); B=digitalRead(contatoM2); C=digitalRead(contatoM3); D=digitalRead(contatoM4); E=digitalRead(contatoM5); F=digitalRead(contatoM6); G=digitalRead(contatoM7); H=digitalRead(contatoM8); I=digitalRead(contatoM9); J=digitalRead(contatoM10); L=digitalRead(contatoM11); M=digitalRead(contatoM12); N=digitalRead(contatoM13); O=digitalRead(contatoM14); Q=digitalRead(contatoM15); R=digitalRead(contatoM16); S=digitalRead(contatoM17); if(tempodecorte()){ // chama funcao para o tempo em que o botao deve ser pressionado para ser considerado um voto if(A==HIGH && enviouA == false){ Serial.write('A'); // armazena A no Serial enviouA = true; delay(5000); } if(A==LOW){ // se mudou o valor de A, altera a flag para quando mudar novamente ele enviar enviouA = false; } // o if do B não deve ter nada a ver com o A, pois são motores diferentes if(B==HIGH && enviouB == false){ Serial.write('B'); // armazena B no Serial enviouB = true; delay(5000); } if(B==LOW){ enviouB = false; } if(C==HIGH && enviouC == false){ Serial.write('C'); // armazena C no Serial enviouC = true; delay(5000); } if(C==LOW){ enviouC = false; } if(D==HIGH && enviouD == false){ Serial.write('D'); // armazena D no Serial enviouD = true; delay(5000); } if(D==LOW){ enviouD = false; } if(E==HIGH && enviouE == false){ Serial.write('E'); // armazena E no Serial enviouE = true; delay(5000); } if(E==LOW){ enviouE = false; } if(F==HIGH && enviouF == false){ Serial.write('F'); // armazena F no Serial enviouF = true; delay(5000); } if(F==LOW){ enviouF = false; } if(G==HIGH && enviouG == false){ Serial.write('G'); // armazena G no Serial enviouG = true; delay(5000); } if(G==LOW){ enviouG = false; } if(H==HIGH && enviouH == false){ Serial.write('H'); // armazena H no Serial enviouH = true; delay(5000); } if(H==LOW){ enviouH = false; } if(I==HIGH && enviouI == false){ Serial.write('I'); // armazena I no Serial enviouI = true; delay(5000); } if(I==LOW){ enviouI = false; } if(J==HIGH && enviouJ == false){ Serial.write('J'); // armazena J no Serial enviouJ = true; delay(5000); } if(J==LOW){ enviouJ = false; } if(L==HIGH && enviouL == false){ Serial.write('L'); // armazena L no Serial enviouL = true; delay(5000); } if(L==LOW){ enviouL = false; } if(M==HIGH && enviouM == false){ Serial.write('M'); // armazena M no Serial enviouM = true; delay(5000); } if(M==LOW){ enviouM = false; } if(N==HIGH && enviouN == false){ Serial.write('N'); // armazena N no Serial enviouN = true; delay(5000); } if(N==LOW){ enviouN = false; } if(O==HIGH && enviouO == false){ Serial.write('O'); // armazena O no Serial enviouO = true; delay(5000); } if(O==LOW){ enviouO = false; } if(Q==HIGH && enviouQ == false){ Serial.write('Q'); // armazena Q no Serial enviouQ = true; delay(5000); } if(Q==LOW){ enviouQ = false; } if(R==HIGH && enviouR == false){ Serial.write('R'); // armazena R no Serial enviouR = true; delay(5000); } if(R==LOW){ enviouR = false; } if(S==HIGH && enviouS == false){ Serial.write('S'); // armazena S no Serial enviouS = true; delay(5000); } if(S==LOW){ enviouS = false; } } }
//Receptor (Arduíno Uno + Shield SIM 900 ICOMSAT 1.1)#include "SIM900.h"#include <SoftwareSerial.h>#include "sms.h"#include "GSM.h"SMSGSM sms;boolean started=false;byte rx=0;char x=0;int pinState = 0;int powerkey = 9; int statuspin = 4;void setup() {Serial.begin(9600); pinMode(rx,INPUT); pinMode(statuspin, INPUT);pinMode(pinState, INPUT);pinMode(powerkey, OUTPUT);pinState = digitalRead(statuspin); if(pinState==LOW){ digitalWrite(powerkey, HIGH); delay(2000); digitalWrite(powerkey, LOW); delay(2000);} Serial.println("GSM Shield testing."); if (gsm.begin(2400)){ Serial.println("\nstatus=READY"); started=true; } else Serial.println("\nstatus=IDLE"); }void loop() { if(Serial.available()){ x = Serial.read(); { if (x =='A'){ sms.SendSMS("+559888021164", "M1 DESARMADO"); delay(5000); } if (x =='B'){ sms.SendSMS("+559888021164", "M2 DESARMADO"); delay(5000); } if (x =='C'){ sms.SendSMS("+559888021164", "M3 DESARMADO"); delay(5000); } if (x =='D'){ sms.SendSMS("+559888021164", "M4 DESARMADO"); delay(5000); } if (x =='E'){ sms.SendSMS("+559888021164", "M5 DESARMADO"); delay(5000); } if (x =='F'){ sms.SendSMS("+559888021164", "M6 DESARMADO"); delay(5000); } if (x =='G'){ sms.SendSMS("+559888021164", "M7 DESARMADO"); delay(5000); } if (x =='H'){ sms.SendSMS("+559888021164", "M8 DESARMADO"); delay(5000); } if (x =='I'){ sms.SendSMS("+559888021164", "M9 DESARMADO"); delay(5000); } if (x =='J'){ sms.SendSMS("+559888021164", "M10 DESARMADO"); delay(5000); } if (x =='L'){ sms.SendSMS("+559888021164", "M11 DESARMADO"); delay(5000); } if (x =='M'){ sms.SendSMS("+559888021164", "M12 DESARMADO"); delay(5000); } if (x =='N'){ sms.SendSMS("+559888021164", "M13 DESARMADO"); delay(5000); } if (x =='O'){ sms.SendSMS("+559888021164", "M14 DESARMADO"); delay(5000); } if (x =='Q'){ sms.SendSMS("+559888021164", "M15 DESARMADO"); delay(5000); } if (x =='R'){ sms.SendSMS("+559888021164", "M16 DESARMADO"); delay(5000); } if (x =='S'){ sms.SendSMS("+559888021164", "M17 DESARMADO"); delay(5000); } else{ x=0; } }}}
…
Adicionado por Edson Diniz ao 14:50 em 12 agosto 2014
om 10 botoes, blz! fiz a montagem e envie o código que foi criado pelo dono do projeto ao Arduino e tudo funcionou perfeitamente, esta aplicação estou usando em minha casa para acionamento de cargas: lampadas tvs e ventiladores e etc... ate aqui tudo tranquilo, acesso pela internet via celular na rede interna e externa tudo perfeito. Agora vou falar o que preciso, eu não sei quase nada de programação da linguagem C++, criei um aplicativo no MIT Inventor 2 e gostaria de usar o meu próprio aplicativo, não sei como criar as regras nos código para enviar para ao arduino é nisso que gostaria da ajuda de meus caros amigos deste conceituado fórum, estou tentando ler algumas coisas sobre este assunto, mais ainda não cheguei a entender, por isso que venho aqui, tentar alguns esclarecimento se possível para acrescentar no desenvolvimento de meus conhecimentos para esta necessidade.
Segue abaixo aplicativo que criei para Android:
tem as duas imagens ON e OFF, pra quando eu clicar ela mudaria a imagem para ON e vise-verso
O aplicativo e o código a baixo é o que eu comprei na PlayStore e está funcionado perfeitamente, gostaria de poder trocar os nomes laterais aos botoes e personalizar de acordo com minhas necessidade. ex colocar o nome do primeiro botão ao invés de ser "A0 OUT 5V" para "GARAGEM" não sei se isto seria melhor, não sei onde estão estas informações no código. agradeço se me for esclarecido estas duvidas.
#include <SPI.h>
#include <String.h>
#include <Ethernet.h>
//-------------------------------------------------------------------
byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };//MAC padrão;
IPAddress ip(192, 168, 1, 120);//Define o endereco IPv4(trocar final);
IPAddress gateway(192, 168, 1, 1); //Define o gateway
IPAddress subnet(255, 255, 255, 0); //Define a máscara de rede
EthernetServer server(8090); // Porta de serviço
//-------------------------------------------------------------------
int AA0 = A0;//Arduino analogica A0;
int AA1 = A1;//Arduino analogica A1;
int AA2 = A2;//Arduino analogica A2;
int AA3 = A3;//Arduino analogica A3;
int AA4 = A4;//Arduino analogica A4;
//-------------------------------------------------------------------
int D2 = 2;//Arduino digital D2; int D3 = 3;//Arduino digital D3; int D4 = 4;//Arduino digital D4; int D5 = 5;//Arduino digital D5; int D6 = 6;//Arduino digital D6; //------------------------------------------------------------------- String readString = String(30); // string para buscar dados de endereço boolean statusA0 = false; // Variável para o status do led boolean statusA1 = false; // Variável para o status do led boolean statusA2 = false; // Variável para o status do led boolean statusA3 = false; // Variável para o status do led boolean statusA4 = false; // Variável para o status do led boolean statusD2 = false; // Variável para o status do led boolean statusD3 = false; // Variável para o status do led boolean statusD4 = false; // Variável para o status do led boolean statusD5 = false; // Variável para o status do led boolean statusD6 = false; // Variável para o status do led //-------------------------------------------------------------------- void setup(){ // Inicia o Ethernet //Ethernet.begin(mac, ip); Ethernet.begin(mac, ip, gateway, subnet); server.begin(); //-----------------------Define pino como saída----------------------- pinMode(AA0, OUTPUT); pinMode(AA1, OUTPUT); pinMode(AA2, OUTPUT); pinMode(AA3, OUTPUT); pinMode(AA4, OUTPUT); pinMode(D2, OUTPUT); pinMode(D3, OUTPUT); pinMode(D4, OUTPUT); pinMode(D5, OUTPUT); pinMode(D6, OUTPUT); //--------------------------------------------------------------------- // Inicia a comunicação Serial Serial.begin(9600); }
void loop(){ // Criar uma conexão de cliente EthernetClient client = server.available(); if (client) { while (client.connected()) { if (client.available()) { char c = client.read(); // ler caractere por caractere vindo do HTTP if (readString.length() < 30) { // armazena os caracteres para string readString += (c); } //se o pedido HTTP terminou if (c == '\n') { //------------------------------------------------------------------ if(readString.indexOf("a0high")>=0)//Recebido do Android; { // O Led vai ser ligado digitalWrite(AA0, HIGH);//Arduino porta digital D2=5V; statusA0 = true; } // Se a string possui o texto L=Desligar if(readString.indexOf("a0low")>=0)//Recebido do Android; { // O Led vai ser desligado digitalWrite(AA0, LOW);//Arduino porta digital D2=0V; statusA0 = false; } //------------------------------------------------------------------ if(readString.indexOf("a1high")>=0)//Recebido do Android; { // O Led vai ser ligado digitalWrite(AA1, HIGH);//Arduino porta digital D2=5V; statusA1 = true; } // Se a string possui o texto L=Desligar if(readString.indexOf("a1low")>=0)//Recebido do Android; { // O Led vai ser desligado digitalWrite(AA1, LOW);//Arduino porta digital D2=0V; statusA1 = false; } //------------------------------------------------------------------ if(readString.indexOf("a2high")>=0)//Recebido do Android; { // O Led vai ser ligado digitalWrite(AA2, HIGH);//Arduino porta digital D2=5V; statusA2 = true; } // Se a string possui o texto L=Desligar if(readString.indexOf("a2low")>=0)//Recebido do Android; { // O Led vai ser desligado digitalWrite(AA2, LOW);//Arduino porta digital D2=0V; statusA2 = false; } //------------------------------------------------------------------ if(readString.indexOf("a3high")>=0)//Recebido do Android; { // O Led vai ser ligado digitalWrite(AA3, HIGH);//Arduino porta digital D2=5V; statusA3 = true; } // Se a string possui o texto L=Desligar if(readString.indexOf("a3low")>=0)//Recebido do Android; { // O Led vai ser desligado digitalWrite(AA3, LOW);//Arduino porta digital D2=0V; statusA3 = false; } //------------------------------------------------------------------ if(readString.indexOf("a4high")>=0)//Recebido do Android; { // O Led vai ser ligado digitalWrite(AA4, HIGH);//Arduino porta digital D2=5V; statusA4 = true; } // Se a string possui o texto L=Desligar if(readString.indexOf("a4low")>=0)//Recebido do Android; { // O Led vai ser desligado digitalWrite(AA4, LOW);//Arduino porta digital D2=0V; statusA4 = false; } //------------------------------------------------------------------ if(readString.indexOf("d2high")>=0)//Recebido do Android; { // O Led vai ser ligado digitalWrite(D2, HIGH);//Arduino porta digital D2=5V; statusD2 = true; } // Se a string possui o texto L=Desligar if(readString.indexOf("d2low")>=0)//Recebido do Android; { // O Led vai ser desligado digitalWrite(D2, LOW);//Arduino porta digital D2=0V; statusD2 = false; } //------------------------------------------------------------------ if(readString.indexOf("d3high")>=0)//Recebido do Android; { // O Led vai ser ligado digitalWrite(D3, HIGH);//Arduino porta digital D2=5V; statusD3 = true; } // Se a string possui o texto L=Desligar if(readString.indexOf("d3low")>=0)//Recebido do Android; { // O Led vai ser desligado digitalWrite(D3, LOW);//Arduino porta digital D2=0V; statusD3 = false; } //------------------------------------------------------------------ if(readString.indexOf("d4high")>=0)//Recebido do Android; { // O Led vai ser ligado digitalWrite(D4, HIGH);//Arduino porta digital D2=5V; statusD4 = true; } // Se a string possui o texto L=Desligar if(readString.indexOf("d4low")>=0)//Recebido do Android; { // O Led vai ser desligado digitalWrite(D4, LOW);//Arduino porta digital D2=0V; statusD4 = false; } //------------------------------------------------------------------ if(readString.indexOf("d5high")>=0)//Recebido do Android; { // O Led vai ser ligado digitalWrite(D5, HIGH);//Arduino porta digital D2=5V; statusD5 = true; } // Se a string possui o texto L=Desligar if(readString.indexOf("d5low")>=0)//Recebido do Android; { // O Led vai ser desligado digitalWrite(D5, LOW);//Arduino porta digital D2=0V; statusD5 = false; } //------------------------------------------------------------------ if(readString.indexOf("d6high")>=0)//Recebido do Android; { // O Led vai ser ligado digitalWrite(D6, HIGH);//Arduino porta digital D2=5V; statusD6 = true; } // Se a string possui o texto L=Desligar if(readString.indexOf("d6low")>=0)//Recebido do Android; { // O Led vai ser desligado digitalWrite(D6, LOW);//Arduino porta digital D2=0V; statusD6 = false; } //------------------------------------------------------------------ // dados HTML de saída começando com cabeçalho padrão client.println("HTTP/1.1 200 OK"); client.println("Content-Type: text/html"); client.println(); client.print("<font size='20'>"); //------------------------------------------------------------------ if (statusA0) { client.print("azeroon");//Ethernet envia para Android; //String apenas letras; } else { client.print("azerooff");//Ethernet envia string para Android; //String apenas letras; } //------------------------------------------------------------------ if (statusA1) { client.print("aoneon");//Ethernet envia para Android; //String apenas letras; } else { client.print("aoneoff");//Ethernet envia string para Android; //String apenas letras; } //------------------------------------------------------------------ if (statusA2) { client.print("atwoon");//Ethernet envia para Android; //String apenas letras; } else { client.print("atwooff");//Ethernet envia string para Android; //String apenas letras; } //------------------------------------------------------------------ if (statusA3) { client.print("athreeon");//Ethernet envia para Android; //String apenas letras; } else { client.print("athreeoff");//Ethernet envia string para Android; //String apenas letras; } //------------------------------------------------------------------ if (statusA4) { client.print("afouron");//Ethernet envia para Android; //String apenas letras; } else { client.print("afouroff");//Ethernet envia string para Android; //String apenas letras; } //------------------------------------------------------------------ if (statusD2) { client.print("dtwoon");//Ethernet envia para Android; //String apenas letras; } else { client.print("dtwooff");//Ethernet envia string para Android; //String apenas letras; } //------------------------------------------------------------------ if (statusD3) { client.print("dthreeon");//Ethernet envia para Android; //String apenas letras; } else { client.print("dthreeoff");//Ethernet envia string para Android; //String apenas letras; } //------------------------------------------------------------------ if (statusD4) { client.print("dfouron");//Ethernet envia para Android; //String apenas letras; } else { client.print("dfouroff");//Ethernet envia string para Android; //String apenas letras; } //------------------------------------------------------------------ if (statusD5) { client.print("dfiveon");//Ethernet envia para Android; //String apenas letras; } else { client.print("dfiveoff");//Ethernet envia string para Android; //String apenas letras; } //------------------------------------------------------------------ if (statusD6) { client.print("dsixon");//Ethernet envia para Android; //String apenas letras; } else { client.print("dsixoff");//Ethernet envia string para Android; //String apenas letras; } //------------------------------------------------------------------ //limpa string para a próxima leitura readString=""; // parar cliente client.stop(); } } } } }…
ada:
Observe que há dois lados distintos na figura. À esquerda temos o lado chamado de "baixa tensão". À direita temos o lado chamado de "alta tensão".
Identificado isto, observe que há apenas uma ligação comum entre os dois lados, e esta ligação é o fio de "GND" (cor preta). Isto é necessário, porque embora os lados sejam "independentes", eles tem que ter a mesma referência de tensão, ou seja, um ponto em comum em relação ao qual todas as tensões no circuito são medidas. Sem este ponto em comum, a tensão "LV" não tem significado (ou "peso") em relação à tensão "HV", e vice-versa. Veja: "LV" é medido em relação ao "GND" da esquerda. E "HV" é medido em relação ao "GND" da direita. Logo, basta interconectar o "GND" da esquerda com o "GND" da direita, para que todos tenham a mesma referência de tensão. Sem isto, o circuitos não funcionarão como esperado. Este é motivo de que sempre o "GND" de um lado será conectado ao "GND" do outro lado. Ok?
Na verdade, na própria plaquinha, já existe uma conexão entre os dois "GNDs", através de trilhas de circuito. Mas costumamos fazer uma conexão adicional "por fora" entre os "GNDs", como uma espécie de reforço. Mas se vc não fizer a ligação "por fora", ainda assim os dois "GNDs" estarão interligados na própria plaquinha conversora.
Agora vamos nos atentar para os demais "fios" conectados à plaquinha.
Do lado esquerdo temos o "LV" (em verde claro), que é a alimentação do circuito de "baixa" tensão da plaquinha. Do lado direito temos o "HV" (em vermelho), que é a alimentação do circuito de "alta" tensão da plaquinha. Ou seja, cada lado da plaquinha, tem sua própria tensão de alimentação, afinal os circuitos precisam ser alimentados para funcionarem, e isto é feito através destes dois terminais, o "LV" e o "HV".
Ocorre que, além de alimentar os circuitos de cada lado da plaquinha, estes dois terminais de alimentação, também determinam quais os níveis lógicos de cada lado da plaquinha. Exemplo: se vc alimenta o lado "LV" com 3.3V, então este lado trabalha com níveis lógicos de 3.3V, ou seja, os sinais conectados aos canais deste lado da plaquinha deverão obrigatoriamente trabalhar com 3.3V. Outro exemplo: se vc alimentar o "HV" com 12V, então os sinais conectados a este lado da plaquinha, deverão trabalhar com níveis lógicos de 12V.
Ou seja: você alimenta um lado, e automaticamente os níveis lógicos deste lado ficam determinados por essa tensão de alimentação. Simples assim.
Mas vc não pode violar uma regra: a tensão de alimentação do lado "LV" deve ser sempre menor que a do lado "HV". Se violar essa regra, os transistores MOSFET existentes no circuito da plaquinha não vão atuar corretamente, e vc ainda correrá o risco de danificar as placas conectadas a cada lado (além da própria plaquinha conversora).
Entendido isto, e alimentando corretamente cada lado (o "LV" e o "HV"), então basta usar os canais para converter os níveis de um lado para outro. Os canais estão representados na figura anterior, por fios de cores diferentes.
Assim por exemplo, um sinal de 3.3V no fio azul do lado "LV", será convertido para um sinal de 5V no fio azul do lado "HV", e vice-versa (e claro: supondo-se que vc alimentou o lado "LV" com 3.3V e o lado "HV" com 5V). Ok?
E é assim que se usa a plaquinha conversora de níveis lógicos. Não estou entrando em detalhes de funcionamento elétrico, porque não sei se vc tem formação em eletrônica, e caso não tenha, iria ficar um tanto "maçante" e também indigesto.
Já sobre a alimentação do seu Sistema, através da Fonte de 9V conectada ao conector DC do DUE, apenas verifique se o Regulador de 5V na placa do Arduino DUE, não está muito quente. Este regulador é aquele que marquei na cor rosa no post anterior. Veja que este Regulador, tem um "corpo" bem pequeno (bem menor que o Regulador de 3.3V), e por isso mesmo, ele não tem capacidade de suportar temperaturas muito altas. Mas quanto seria o normal??? Faça o seguinte: toque de leve com um dedo, o corpo do Regulador (mas sem tocar nos seus terminais metálicos!!!!!!!!), e caso consiga ficar com o dedo ali sem o calor te incomodar (como eu disse, de leve, sem apertar!!!), é porque a temperatura está normal. Do contrário, talvez seja melhor alimentar o Sistema com uma fonte entre 7V e 7,5V via conector DC, a fim de diminuir o calor produzido no Regulador em questão (veja que falei sobre isto no post anterior).
E sobre a questão de falha de 90% que vc mencionou na comunicação entre o DUE e o Nextion, pode ser sim um "problema de ruído". Mas provavelmente não seria um ruído como vc deve estar imaginando. Vou esclarecer.
Ocorre que, quem faz a conversão de níveis lógicos na plaquinha conversora, são os transistores MOSFET que tem nela. No entanto, estes MOSFETs da plaquinha, não são excepcionalmente "rápidos". Mas como assim rápidos??? Veja: quando um nível lógico muda de "0" para "1", ou de "1" para "0", essa mudança ("comutação") deve ser a mais rápida possível. Do contrário, o circuito deixa de ser digital, e passa a ser analógico. Em Sistemas Digitais, só existem dois níveis: o "0" e o "1". Em Sistemas Analógicos existem infinitos níveis. Assim se a mudança de níveis for "lenta", passaremos a ter infinitos níveis, o que confundirá o circuito digital fazendo que ele interprete erroneamente se é "0" ou se é "1". Então a encrenca estará feita, pois os comandos a que vc se refere são enviados como sequências de "1" e "0". As placas não se entenderão, pois um ou outro nível ("0" ou "1") será interpretado erroneamente.
Infelizmente, estes MOSFETs da plaquinha, não são nenhum foguete, e na verdade são até lentos, o que pode provocar a interpretação errônea dos níveis em um ou outro lado (geralmente a falha ocorre no lado "HV", mas não vou entrar neste detalhe). E não vale a pena trocá-los por MOSFETs mais rápidos, a não ser que vc queira fazer isso de qualquer forma.
O que fazer então??? Há diversas outras soluções, inclusive usando outros conversores digitais, e realmente rápidos. Há uma infinidade deles no mercado (mas no Brasil nem sempre é fácil encontrá-los). E claro, tem que saber escolher o conversor adequado para cada circuito.
Esta plaquinha conversora funciona sim, mas tem suas limitações onde sinais de transição rápidos são necessários (o que é quase certo no caso do Nextion).
O que fazer então? Primeiro, precisa ter certeza que o problema é a velocidade de transição (mais comumente chamada de velocidade de "comutação"). Isto pode ser tecnicamente trabalhoso, e exigiria algum conhecimento técnico mais aprofundado.
Mas no seu caso, há uma forma muito segura e confiável de conseguir o mesmo resultado, sem usar a plaquinha conversora. Como? veja o circuito que preparei na figura a seguir:
(clique na figura para "zoom")
Você só precisará de dois resistores: um de 2k e outro de 1.2k (também chamado de "1k2"). Eu calculei estes dois resistores, para converter os níveis de 5V do sinal "TX" do Nextion, para os níveis de 3.3V do "RX" do DUE, e sem forçar estes dois sinais. E eles conseguem fazer isso na velocidade necessária.
Observe que devem estar ligados exatamente como eu mostro na figura, e inclusive, os dois resistores devem estar fisicamente mais próximos do DUE do que do Nextion (veja que está dessa forma na figura).
A tolerância dos resistores pode ser 5% (a famosa faixa "dourada"), e a potência não é relevante neste caso.
E sobre o outro sinal na cor amarela??? Este NÃO precisa de conversor!!! ocorre que o sinal de saída digital de 3.3V é totalmente compatível com uma entrada digital de 5V. E este é o caso do sinal de saída "TX" do DUE que vai para o sinal de entrada "RX" do Nextion.
Faça o teste, e verificará o funcionamento. E vamos esperar que o problema dos 90% que vc relatou seja isso. Se não for, vamos ver outras alternativas. Mas torça pra essa que eu te mostrei, pois é bastante simples, né?
Ah, olhei o link sobre o Nextion que vc passou, e achei muito legal. Recomendo a todos que estiverem lendo este post.
Abrçs,
Elcids
…
Adicionado por Elcids Chagas ao 23:24 em 20 fevereiro 2019
s o próprio EMI gerado pelo circuito, é mais de 90% provocado pelo overshoot (intensidade e frequência). E certamente esse EMI será um imenso problema em equipamentos comerciais (se for muito alto, nem será aprovado em ensaios de certificação).
Então agora podemos abrir o jogo um pouco mais, assim colaborando com outros que venham aqui no LDG procurando informação relacionada.
Vamos resumir as coisas assim:
1) o chaveamento da corrente em L2, gera impulsos de tensão que tendem a ser os impulsos unitários, porém estes são do mundo real (tem amplitude limitada e a largura do pulso não é zero). Estes impulsos nada mais são portanto, do que "pacotes" de energia que que são enfiados pela guela do capacitor na saída do seu Conversor DC/DC. Cada novo impulso acrescenta um novo pacote de carga "dQ" ao Capacitor de saída, o que por sua vez se traduz num delta de tensão. Sem uma carga resistiva na saída, com o passar do tempo, a tensão sobre esse Capacitor tenderá a alcançar praticamente quase o mesmo valor do impulso, e isto ocorre porque simplesmente estamos pegando um "pacote" de carga "dQ", e jogando em cima de um valor de capacitância de saída muito alto (no seu caso, C4 de 2000uF), e pela equação V = Q/C, pode-se calcular não somente o degrau de tensão dV, mas a própria tensão final sobre o Capacitor após cada novo impulso.
2) mas ao termos uma carga resistiva na saída, parte de cada "dQ" é também usado para alimentar esta carga resistiva, o que implica que esta carga resistiva atua justamente como o "outro lado do cabo de guerra", e assim "trabalha" no sentido de reduzir a tensão sobre o Capacitor de saída. Ao final das contas, espera-se que a taxa de impulsos por segundo, seja suficiente para equilibrar esse cabo de guerra, fazendo com que a tensão sobre o Capacitor se estabilize em torno de um valor médio (na realidade, ela acaba oscilando em torno do valor médio, e este é o ripple real na saída). A taxa de impulsos é a própria frequência de chaveamento, e ela acaba por bombear impulsos de "dQ" para o Capacitor de saída. Maior taxa (frequência), compensação mais rápida. Menor taxa, compensação mais lenta. Um algorítimo de controle de malha fechada, então nada mais faz do que ajustar essa taxa para que a saída tenha o comportamento de tensão esperado: quase constante para uma tensão DC, ou em "arco" crescente ou decrescente para uma saída senoidal. Claro que neste último caso, você poderá variar a própria tensão de entrada (como vc mencionou que já o fez), e assim terá também uma variável a mais na sua equação, que será a intensidade de cada pacote de energia "dQ", e assim tendo um maior controle sob o comportamento da tensão de saída.
3) o fato de ser Buck, Boost, é apenas o resultado da manipulação da intensidade e frequência dos pacotes "dQ", já que estes acrescentam energia ao Capacitor de saída, determinando a tensão sobre este capacitor, ou seja, simplesmente um resultado da conversão V = Q/C, considerando que parte da energia acumulada no Capacitor de saída está sendo drenada por uma carga resistiva (formando o "cabo de guerra" entre consumo e "bombeamento" de energia).
4) e o fato de ser saída positiva ou negativa, é apenas a configuração de como vc direciona os impulsos "dQ" para o Capacitor de saída, ou seja: determinado pela polaridade do Diodo na saída (no seu circuito, D2), que é o elemento chave nisto. Obviamente a polaridade do Capacitor deverá estar de acordo com a tensão resultante desse direcionamento.
5) as diversas configurações mostradas no "slyu036" da Texas, nada mais são do que uma exploração das possíveis variações do que foi descrito acima, inclusive recombinando os circuitos e aplicando o controle adequado ao chaveamento para se obter as características de conversão DC/DC desejadas.
6) uma pequena parte do "dQ" do impulso, acaba injetando energia em um "inesperado" Circuito Tanque LC, composto pelo próprio Indutor do chaveamento de corrente e pela capacitância parasítica existente ali, resultando na oscilação amortecida de alta frequência determinada por Freq = 1/(2*Pi*raiz(LC)). Observe que qualquer chaveamento da corrente do Indutor, irá provocar o impulso de tensão, devido ao Ldi/dt, e havendo alguma capacitância parasítica formando um Circuito Tanque LC, certamente existirá o overshoot senoidal amortecido, na frequencia natural do tanque LC.
7) sempre haverá dois overshoots, pois o indutor é chaveado duas vezes em cada ciclo do seu PWM. Em um dos edges do PWM, a capacitância parasítica do Diodo formará com o Indutor, o circuito tanque LC, resultando em um overshoot. No edge seguinte, será a capacitância parasítica entre Gate e Dreno do MOSFET que se juntará ao Indutor para formar o tanque LC, e um overshoot com outra frequencia e intensidade ocorrerá.
8) e finalmente: como capacitores também são elementos de acoplamento de tensão, uma capacitância parasítica entre dois pontos, acoplará o overshoot no outro nó correspondente ao outro lado desse capacitor. É por isso Dário, que no seu próprio sinal PWM também acaba aparecendo o overshoot (mesma frequência, mas com outra intensidade, que pode ser calculada por um divisor de tensão com impedâncias imaginárias).
Agora sobre o tratamento:
1) observe que estes circuitos procuram usar diodos do tipo "Schottky", pois estes além de serem rápidos tem uma menor "capacitância de barreira" que os diodos "PN" convencionais. Os "Schottky" também tem uma menor resistência de corpo (BULK), o que diminui as perdas por efeito Joule. Observe que nos APNs, vc sempre verá diodos "Schottky" sendo usados (naquela plaquinha da China, também).
2) observe qual a capacitância parasítica intrínseca entre Dreno e Gate do MOSFET, e claro ela deve ser a menor possível, e se deve tomar o cuidado para não acrescentar circuitos ali que causem aumento significativo dessa capacitância entre Dreno e Gate. Observe também que devido ao proprio liga/desliga do MOSFET, capacitâncias parasíticas entre Dreno e Source também podem injetar um "dQ" no Dreno, causando também um overshoot. Logo, a chave aqui, é escolher MOSFETs que tenham sido projetados para chaveamento em circuitos conversores DC/DC de alta frequência, pois certamente suas capacitâncias terão valores menores. Usar MOSFETs originalmente projetados apenas para um ON/OFF convencional, poderá ser um tiro no pé.
3) o Capacitor Eletrolítico de Alumínio de alto valor usado como parte essencial do conversor DC/DC, não irá amenizar o overshoot na saída, porque este tipo de Capacitor tem também uma alta indutância equivalente (ESI), e portanto não filtra a alta frequência do overshoot. Para esta tarefa, sempre se deve usar em paralelo com o Eletrolítico de Alumínio (no seu caso o "C4" de 2000uF), ou um Capacitor de Tântalo ou um de Cerâmico, os quais tem uma baixa indutância equivalente. Veja que nos datasheets desses conversores DC/DC integrados, sempre é especificado o acréscimo de um Capacitor de Tântalo ou do tipo Cerâmico, justamente pelo motivo delineado. Usar combinação de Tântalo e Cerâmico, também é uma ótima alternativa, principalmente em termos de custo e eficiência.
4) usar técnicas pontuais caso seja realmente necessário, como os "snubers" do artigo que vc citou (o do Marcin Walczak). Mas antes disso, deve-se obrigatoriamente aplicar as técnicas convencionais citadas acima (todas devem ser usadas, sem exceção). Caso o overshoot ainda resulte ser acima do mínimo aceitável para sua aplicação, então parte-se para aplicar técnicas pontuais e especializadas.
Fico por aqui, pois um pouco mais disso vai me dar overshoot.
Mas claro, se houver algo mais que eu possa ajudar e esteja ao meu alcance, vamos em frente.
Abrçs,
Elcids…
Adicionado por Elcids Chagas ao 5:46 em 14 março 2019
(LED) após um período de tempo quando o acionamento é feito pelo Botão ou pelo Sensor PIR, então foi necessário acrescentar mais um estado, com o que a Máquina passou a ter 3 estados.
Nesta Parte 1, estarei publicando a implementação do Sistema de Controle da Lâmpada do Aquário, usando Arduino UNO. Mas a implementação poderá ser estendida a qualquer outra Placa disponível que utilize a Plataforma Arduino (Nano, ESP32, ESP8266, Due, etc).
Nos posts seguintes a este, a implementação será descrita na seguinte ordem, onde cada item será um "post", iniciando pela Parte 2:
2) descrição dos elementos e estruturas de dados usados na implementação, e das implicações resultantes de algumas destas definições.
3) descrição dos Estados e Eventos necessários para o Sistema funcionar, e das implicações resultantes.
4) descrição da técnica básica de implementação de uma Máquina de Estados (na Plataforma Arduino e de forma genérica), usando como referência este exemplo do Controle do Aquário e/ou outros exemplos simples.
5) apresentação de possibilidades para a implementação, usando técnicas mais "avançadas" ou sofisticadas.
Assim a Parte 1, efetivamente se inicia a seguir:
O Diagrama de Estados da Máquina de Estados que controla este Sistema, pode ser visto na figura a seguir:
(clique na figura para "zoom")
O Diagrama em si é simples e praticamente dispensaria explicações. Mas eu entendo que para quem for principiante poderá ter dificuldades em entender a dinâmica do funcionamento, e por isso mesmo (como dito anteriormente), em outro post irei descrever a técnica e a metodologia por trás da implementação dessa Máquina de Estados.
A implementação foi feita também em Simulação no Proteus, o que dá grande flexibilidade para testar as diversas condições e possibilidades de configuração do código. O Hardware para a Simulação no Proteus, é mostrado na figura a seguir:
(clique na figura para "zoom")
Observar que embora na simulação tenha sido utilizado um Sensor PIR de autoria do "TEP" ("The Engineering Projects"), isto é quase um "enfeite", uma vez que na simulação o PIR poderia ser simplesmente substituído por um Botão (ou então um Monoestável e um Botão).
Observar também, que após a inicialização, algumas informações são exibidas no Terminal do Arduino, a saber:
- o "total de comandos": isto está descrito em mais detalhes logo adiante no texto.
- o "tempo de apagamento automático", que é o tempo que a Lâmpada apagará automaticamente após ter sido ligada pelo Botão ou pelo Sensor PIR. Observar que no código da simulação, eu deixei apenas 20 segundos, para ficar mais dinâmico o teste (ou seja, não ter que esperar muito pra ver se o apagamento automático está funcionando). Mas no código aqui publicado, este tempo está setado em 60 segundos, mas deve ser alterado conforme se deseja (ele está definido logo no início do código).
- a Data/Hora atual lida do RTC DS3231 (incluindo o Dia da Semana, informado em Português). Sobre este ponto, no código da simulação foi setado através do Botão apertado logo que o Arduino é iniciado, um dia e horário que permitisse verificar rapidamente o funcionamento para os Dias e Horários de acendimento e apagamento programados no Sistema. E foi verificado o correto funcionamento (na simulação, programei para ligar às 17:01 e para desligar às 17:03 do domingo).
Sobre o "total de comandos" vou esclarecer.
O método utilizado para se "programar" os Dias e Horários que se quer ligar/desligar a Lâmpada, é utilizando um "Vetor de Comandos", ou seja, uma "Lista de Comandos". Estes Comandos podem estar em qualquer ordem no Vetor (a "Lista"), uma vez que está descrito no próprio Comando qual o Dia e Horário que o comando deve ser executado. Vejamos um exemplo na figura a seguir, onde são mostrados 4 Comandos na "Lista":
(clique na figura para "zoom")
Observe que o primeiro elemento de um Comando, é o Dia da Semana (segunda, sexta, domingo, etc), seguido pelo horário (Hora e Minuto), e por último se o Comando é para ligar ou desligar a Lâmpada. Assim, já adiantando parte de como a coisa funciona (pois isto será efetivamente descrito no próximo post): o tal "Vetor de Comandos" é uma "Lista de Comandos", a qual será "varrida" pelo código para execução de cada um dos Comandos, assim ligando ou desligando a Lâmpada no Dia e Horário descrito em cada Comando (e claro, o Dia/Horário atual é fornecido pelo RTC DS3231 do Sistema).
Notar que embora os Comandos possam estar na Lista em qualquer ordem, é aconselhável por motivos óbvios de organização, que se procure colocar sequencialmente na Lista um Comando para ligar seguido de um Comando para desligar. Ou seja, assim fica fácil observar olhando a sequência na Lista (ou Vetor), como irá funcionar toda a programação feita para o Controle da Lâmpada.
Pode-se ter quaisquer quantidades de Comandos na Lista. Cada Comando ocupa 4 bytes na Memória RAM do Arduino, e uma vez que ainda resta de RAM bem mais de 1000 bytes, então isto permitiria se ter bem além de 250 comandos programados para execução. Ou seja, tranquilo em relação à uma eventual necessidade de programação de uma grande quantidade de comandos.
No código que está anexado nesta publicação, eu deixei apenas 6 comandos, e por este motivo este é o valor mostrado no Terminal do Arduino.
Acrescentar Comandos é simples. A única coisa necessária é colocá-los na Lista, a qual está logo no início do código (lá a Lista é chamada de "Vetor_Comandos"). Mais nada precisa ser feito.
Para ilustrar essa facilidade, é mostrada na figura a seguir, como a "Lista" com os 6 comandos está definida no código que estou disponibilizando neste post:
(clique na figura para "zoom")
Observar que os nomes dos dias da semana podem ser escritos em Português, pois estes nomes também foram definidos no início do código (e são compatíveis com os nomes em inglês definidos na Biblioteca DS3231).
O código do Arduino, os Arquivos para Simulação, e o Diagrama de Estados (Visio e PDF), estão neste link:
Lampada_Aquario_01.zip
O Sistema foi testado, mas caso seja detectada alguma anomalia no funcionamento, basta sinalizar aqui, que irei considerar logo que possível.
Não se deixe enganar achando que existe alguma complexidade. Não existe. Ocorre que o tratamento "anti-bouncing" para o Botão (e algo semelhante para o PIR), exigiu rotinas um pouco maiores. Mas isto é apenas devido ao "anti-bouncing", e nada mais. E também foram necessárias algumas rotinas a mais para o RTC, com funções bem simples.
Sobre o funcionamento e porque o Sistema foi implementado dessa forma (usando os "Comandos"), será abordado nos próximos posts.
Abrçs,
Elcids…
Adicionado por Elcids Chagas ao 21:33 em 14 setembro 2019