da equação:
Equação 1
Onde:
P - Potência de RF em Watts
Vpap – Tensão pico a pico do sinal de RF em Volts
Z0 – Impedância característica em Ohms
Figura 1
Com o objetivo de detectar níveis de RF entre -45dBm (31.6nW) à -30dBm (1µW), deve ser levado em conta o fato de que diodos operando com sinais abaixo de -20dBm não seguem a lei da linearidade.
Nesta condição os diodos seguem a Lei do Quadrado (Square Law) que é uma função exponencial da tensão de saída Vo em relação a potência de entrada (P). A tensão de saída do detector deve ser estimada com base na equação . Referência [3]
Equação 2
Onde:
Vo = tensão DC de saída
K – Constante de proporcionalidade
- Coeficiente quadrático.
Glen Leinweber, referência [4] sugere dividir a curva de resposta do diodo detector em tres regiões conforme o nível de potência aplicado:
Linear acima de 20 dBm.
Transição -20 dBm a 20 dBm
Lei do quadrado abaixo de -20 dBm.
Além desta proposição sugere um limite inferior prático para este tipo de detector de -60 dBm (223,6 µV em 50 Ω)
Neste projeto considero somente a operação na região de -30 dBm, região em vermelho no gráfico abaixo.
Figura 2
Estimativa da tensão de saída, baseado na AN 986, da HP referência [3], para o diodo 5082-2824 em 2 GHz, polarizado com uma corrente de 20uA, por analogia podemos esperar algo um pouco melhor com o diodo HSMS2825, que basicamente tem menor capacitância. E o gráfico da tensão estimada de saída do HSMS 282B em 850 MHz, polarizado com uma corrente de 3 uA conforme referência [1]
Figura 3
Conforme referência [3] , pode assumir valores entre 0.8 e 2 , O valor de
(Detection Law) depende da capacitância do diodo da freqüência e resistência da carga do detector.
Figura 4
Conforme orientação contida na referencia [1] , uma maneira de anular a variação da tensão de saída com variação da temperatura, é utilizar um amplificador diferencial conforme figura.
Figura 5
O fato dos diodos serem praticamente idênticos torna o cancelamento da variação térmica efetivo, desde que mantido a mesma corrente DC de polarização (Bias) nos dois diodos, o cancelamento ocorre na subtração que acontece entre VF na entrada + e VF da entrada – do amplificador diferencial, esta variação não pode ser desprezada no projeto conforme pode ser observado na curva IfxVf .Já a variação de Rd x If acarretara em erros de linearidade, ai a correção já é um pouco mais complexa, porém pode ser feita através do uso de microcontroladores.
O circuito
Serão duas topologias analisadas a primeira com compensação térmica e a segunda sem, porém com maior sensitividade.
Escala de operação em vermelho:
Figura 6
Em acordo com estes dados foi projetado o seguinte :
São utilizados os dois diodos que fazem parte do package SOT 143, D2 Retificando o sinal de RF e D1 fornecendo a tensão do ruído térmico proporcional a temperatura e conectado a entrada + do amplificador diferencial. D1 e D2 estão polarizados com uma corrente de aproximadamente 20 uA através de R1/R3
O Amplificador diferencial utilizado é o AD 620, escolhido pela sua excelente relação custo benefício e facilidade de ser encontrado. As características técnicas determinantes são: Baixo ruído, baixo drift, alta precisão e o ganho (G) pode ser “programado” apenas com um resistor (R6) que neste caso esta calculado para um ganho aproximado de 200, para proporcionar uma tensão (Vo) de fundo de escala de 4V, quando o detector estiver sob uma potência de -30dBm. Caso seja necessário um ganho 1 basta omitir R6.
Equação 3
Onde:
K = x1000
G = Ganho
Com este circuito ai na “ bancada” espero obter uma variação de tensão (VO) entre 0.4V e 4 V, dentro da escala de -45dBm a -30dBm, na Banda L, e uma boa estabilidade com relação a variação de temperatura. Usei fonte simétrica por conveniência pois já tenho uma disponível no sistema onde este circuito será parte se houver interesse em usar este circuito com fonte simples sugiro o leitor dar uma olhada na refêrencia [2].
Figura 7
Nesta segunda concepção não há a compensação de temperatura, porém a sensitividade é o dobro da topologia anterior,o sinal de RF tem o semi ciclo positivo e negativo retificados por D1 e D2, foi incluído um ajuste de tensão de offset para ”zerar” o detector quando necessário. O valor de R6 foi dobrado afim de reduzir o ganho para manter o FS (fundo de escala) em 4 Volts. O fato de estarem dois diodos conectados na entrada de RF não altera o desempenho do circuito, observando a curva de Rd X IF,posso prever uma resistência de entrada maior do que 50K.
Certamente será a opção preferida pelos radioastronomos amadores. No caso deste ser utilizado como sensor em um nanowattímetro microcontrolado, a correção térmica e correção de linearidade poderá ser feita através de uma equação de ajuste ou tabela armazenada no firmware. Meu objetivo com este circuito é testar o limite da detecção com esta técnica.
Figura 8
Referências:
[1] Angilent Technologies.
Suface Mont RF Schottky Barrier Diodes, Technical Data
[2] Denton Bramwell, K7OWJ.
The Microwatter, june 1997, QST Magazine. Reprint ARRL Handbook 2003
[3] Hewllet Packard.
Square Law and Linear Detection, Application Note 986
[4] Glen Leinweber
Radio Astronomy Supplies Ap.6, Square Law Diode Detectors in 50 ohm Systems.
…
Adicionado por Joe Nova para RF ao 8:43 em 14 março 2011
ystal.h> //Inclui a biblioteca do LCD#include <Wire.h>#include <Time.h>#include <DallasTemperature.h>#include <OneWire.h>#include <DS1307RTC.h> #define ONE_WIRE_BUS 10#define RELAY13 //pino do releOneWire oneWire(ONE_WIRE_BUS);DallasTemperature sensors(&oneWire);DeviceAddress insideThermometer = { 0x28, 0xDF, 0x63, 0x51, 0x05, 0x00, 0x00, 0xC3 };// Pinos de comando dos botões do relógio#define clockSet A0 // Pinos de comando dos botões do relógio#define clockUp 9#define clockDown 8 //Estados de Clock#define stClockRunning 0#define stSetDay 1 //define o ano#define stSetMonth 2 //define o mes#define stSetYear 3 //define o dia#define stSetDow 4 //define o dia da semana#define stSetHour 5 //define a hora#define stSetMinute 6 //define o minuto#define stSetSecond 7 //define o segundoint pinorelay13 = 13; int stat = stClockRunning; LiquidCrystal lcd(12, 11, 5, 4, 3, 2); //configuração dos pinos do lcd void Print(int number){ lcd.print(number/10); lcd.print(number%10);} // Preenchimento do display LCDvoid printTime(){ lcd.setCursor(2,1); Print(hour()); lcd.print(":"); Print(minute()); lcd.print(":"); Print(second()); lcd.setCursor(3,0); Print(day()); lcd.print("/"); Print(month()); lcd.print("/"); Print(year()); lcd.setCursor(0,0); lcd.noCursor(); // Cursor invisível lcd.noBlink(); // Efeito blink desligado if (stat != stClockRunning) lcd.print("*"); else lcd.print(" "); simbolorelogio(); lcd.setCursor(0,1); lcd.write(3); switch(stat) { case stSetDay: lcd.setCursor(1,0); lcd.print("d "); lcd.setCursor(4,0); lcd.cursor(); // Cursor visível lcd.blink(); // Cursor piscando break; case stSetMonth: lcd.setCursor(1,0); lcd.print("m "); lcd.setCursor(7,0); lcd.cursor(); // Cursor visível lcd.blink(); // Cursor piscando break; case stSetYear: lcd.setCursor(1,0); lcd.print("a "); lcd.setCursor(12,0); lcd.cursor(); // Cursor visível lcd.blink(); // Cursor piscando break; case stSetHour: lcd.setCursor(1,0); lcd.print("h "); lcd.setCursor(3,1); lcd.cursor(); // Cursor visível lcd.blink(); // Cursor piscando break; case stSetMinute: lcd.setCursor(1,0); lcd.print("M "); lcd.setCursor(6,1); lcd.cursor(); // Cursor visível lcd.blink(); // Cursor piscando break; case stSetSecond: lcd.setCursor(1,0); lcd.print("s "); lcd.setCursor(9,1); lcd.cursor(); // Cursor visível lcd.blink(); // Cursor piscando break; }} // Lê pino usando limiar, como um interruptor, isto é,// interruptor pressionado primeira vez liga, pela segunda vez desligaint readPinSwitch(int pin, int threshold){ if (digitalRead(pin)) { unsigned long tt = millis(); while (digitalRead(pin)); if ((millis() - tt) > threshold) return 1; else return 0; } else return 0;} //Lê pino usando limiarint readPin(int pin, int threshold){ if (digitalRead(pin)) { unsigned long tt = millis(); while ((digitalRead(pin) && (millis() - tt) <= threshold)); if (digitalRead(pin)) return 1; else return 0; } else return 0;} // obter novo status, se houverint getStat(){ if (readPinSwitch(clockSet,300)) if (stat == stSetSecond) return stClockRunning; else return stat+1; else return stat;} // definir Arduino e tempo do RTCvoid setRTCTime(int hour, int minute, int second, int day, int month, int year){// define tempo do Arduino setTime(hour,minute,second,day,month,year); time_t t = now();// define tempo do RTC RTC.set(t);} void simbolorelogio(){ byte relogio[8] = { B00000, B01110, B10101, B10111, B10001, B01110, B00000, B00000}; lcd.createChar(3, relogio); // Cria o caractere personalizado de um relogio}void printTemperature(DeviceAddress deviceAddress){float tempC = sensors.getTempC(deviceAddress);if (tempC == -127.00) {lcd.print("Error");}else{lcd.setCursor(11,1); lcd.print(tempC);lcd.print("");}} void setup(){ pinMode(pinorelay13, OUTPUT); //Define o pino como saidasensors.begin(); sensors.setResolution(insideThermometer, 10); // Start the I2C interface Wire.begin(); // Start the serial interface Serial.begin(9600);lcd.begin(16, 2); lcd.clear(); // start with a blank screensetSyncProvider(RTC.get); // the function to get the time from the RTC if(timeStatus()!= timeSet) pinMode(clockUp,INPUT); // configura os pinos dos botões como entrada pinMode(clockDown,INPUT); pinMode(clockSet,INPUT); if(timeStatus()!= timeSet) // verifica status do RTC e retorna erro { lcd.setCursor(0,0); lcd.print("Erro do RTC:"); lcd.setCursor(0,1); lcd.print("Ajuste o Relogio"); delay(3000); lcd.clear(); }} int oldStat = stat;unsigned long t=millis(); void loop(){ digitalClockDisplay(); delay(1000);}void digitalClockDisplay(){ // digital clock display of the time Serial.print(hour()); printDigits(minute()); printDigits(second()); Serial.print(" "); Serial.print(day()); Serial.print(" "); Serial.print(month()); Serial.print(" "); Serial.print(year()); Serial.println(); }void printDigits(int digits){ // utility function for digital clock display: prints preceding colon and leading 0 Serial.print(":"); if(digits < 10) Serial.print('0'); Serial.print(digits);{/*Comando utilizado apenas pra ficar enviando via USB a hora atualpara que possam monitorar no "serial monitor" do simulador Arduinoe ver se esta tudo funcionando de acordo*/{ //Aciona o rele digitalWrite(pinorelay13, HIGH); delay(50); //Aguarda 2 Horas //Desliga o rele digitalWrite(pinorelay13, LOW); delay(50); //Aguarda 5 segundos e reinicia o processo sensors.requestTemperatures();printTemperature(insideThermometer);lcd.setCursor(17,1);delay(04/33/20); // //Desliga o rele delay(04/36/20); //Aguarda 5 segundos int value = 0; printTime(); // rotina que imprime o tempo no lcd delay(100); stat=getStat(); if (stat != oldStat) { t=millis(); oldStat = stat; } else if ((stat != stClockRunning) && ((millis() - t) > 30000)) //tempo em milisegundos que o ajuste do relógio ficará disponível para ser alterado stat=stClockRunning; switch(stat) { case stClockRunning: break; case stSetDay: // inicializa value value=day(); //si botao UP (para cima) for pressionado while(readPin(clockUp,200)) { value++; if (value > 31) value=1; setRTCTime(hour(),minute(),second(),value,month(),year()); printTime(); } //si botao DOWN (para baixo) for pressionado while(readPin(clockDown,200)) { value--; if (value < 1) value=31; setRTCTime(hour(),minute(),second(),value,month(),year()); printTime(); } break;// ver comentários em stSetDay case stSetMonth: value=month(); while(readPin(clockUp,200)) { value++; if (value > 12) value=1; setRTCTime(hour(),minute(),second(),day(),value,year()); printTime(); } while(readPin(clockDown,200)) { value--; if (value < 1) value=12; setRTCTime(hour(),minute(),second(),day(),value,year()); printTime(); } break; case stSetYear: value=year(); while(readPin(clockUp,200)) { value++; if (value > 2050) value=2000; setRTCTime(hour(),minute(),second(),day(),month(),value); printTime(); } while(readPin(clockDown,200)) { value--; if (value < 2000) value=2050; setRTCTime(hour(),minute(),second(),day(),month(),value); printTime(); } break; case stSetHour: value=hour(); while(readPin(clockUp,200)) { value++; if (value > 23) value=0; setRTCTime(value,minute(),second(),day(),month(),year()); printTime(); } while(readPin(clockDown,200)) { value--; if (value < 1) value=24; setRTCTime(value,minute(),second(),day(),month(),year()); printTime(); } break; case stSetMinute: value=minute(); while(readPin(clockUp,200)) { value++; if (value > 59) value=0; setRTCTime(hour(),value,second(),day(),month(),year()); printTime(); } while(readPin(clockDown,200)) { value--; if (value < 0) value=59; setRTCTime(hour(),value,second(),day(),month(),year()); printTime(); } break; case stSetSecond: value=minute(); while(readPin(clockUp,200)) { value++; if (value > 59) value=0; setRTCTime(hour(),minute(),value,day(),month(),year()); printTime(); } while(readPin(clockDown,200)) { value--; if (value < 0) value=59; setRTCTime(hour(),minute(),value,day(),month(),year()); printTime(); } } }}}
mas está dificil e tambem falta os dias da semana.…
Adicionado por Antonio Gomes ao 19:36 em 27 agosto 2014
Veja como ficou:
Esse é o codigo:
// incluir a library do LCD#include <LiquidCrystal.h>
// inicializar a library do LCD com nos pinosLiquidCrystal lcd(11, 12, 7, 8, 9, 10);int holdTime = 1500; // tempo do hold (botao pressionado)int botao = 0; // botao apertadoint hold = 0; // botao pressionado x tempolong onTime = 0; // conta tempo botao apertado
void setup() { // Mensagem de abertura. lcd.begin(16, 2); lcd.print("5 botoes + hold v1"); lcd.setCursor(0,1); lcd.print("by Renato Brant"); delay(1000); lcd.clear(); long onTime = 0; pinMode (A5, INPUT); lcd.clear();}
void loop() { int valorBotao = analogRead(5); // le valor da tensao causado pelas resistencias dos botoes int botao = 0; // considera que nenhum botao esta apertado // vamos definir o valor lido na porta analogica para cada botao if (valorBotao > 304 && valorBotao < 394) botao = 1; //botao UP if (valorBotao > 484 && valorBotao < 574) botao = 2; //botao OK if (valorBotao > 666 && valorBotao < 749) botao = 3; //botao RIGHT if (valorBotao > 824 && valorBotao < 887) botao = 4; //botao LEFT if (valorBotao > 938 && valorBotao < 989) botao = 5; //botao DOWN // agora começa o sistema para fazer o HOLD // enquanto nenhum botao é apertado, nos guardamos o valor do millis no onTime e deixamos o valor do HOLD zerado if (valorBotao < 304){ onTime = millis(); hold=0; } // quando algum botao for apertado E o tempo que o botao esta apertado for maior que o holdTime, o valor do HOLD vai para 1. if (valorBotao > 304 && ((millis() - onTime) > holdTime)) hold =1;//Neste ponto, já temos as duas variaveis que nos interessa://botao => retorna o numero do botao que está sendo apertado//hold => vira 1 se algum botão for apertado por mais de 3 segundos//Para uma melhor visualização, vamos mandar alguns valores para o LCD
//obs: agora é só "firula"
// vamos visualizar o valor lido pela porta analogica
lcd.clear();
lcd.setCursor(0,0); lcd.print("V"); lcd.print(valorBotao);
// vamos visualizar o valor de "botao" lcd.setCursor(5,0); lcd.print("B"); lcd.print(botao); // vamos ver quanto tempo algum botao está apertado lcd.setCursor(8,0); lcd.print("T"); lcd.print((millis() - onTime)/1000); // vamos ver se o "hold" está habilitado lcd.setCursor(11,0); lcd.print("H"); lcd.print(hold); // na segunda linha, vamos mostrar o estado de forma escrita lcd.setCursor(0,1); if (botao == 0) lcd.print(" "); else if (botao == 1) lcd.print("UP"); else if (botao == 2) lcd.print("OK"); else if (botao == 3) lcd.print("RIGHT"); else if (botao == 4) lcd.print("LEFT"); else if (botao == 5) lcd.print("DOWN"); if (hold == 1) lcd.print("+HOLD"); delay(250);}
Aqui estão os esquemas:
Eu ainda não montei fisicamente, mas assim que eu tiver um tempo, eu farei e colocarei o video aqui.
…
Adicionado por renatobrant ao 16:56 em 17 janeiro 2012
era alterar o codigo, para que quando eu clicasse NESSA imagem, que me acendesse um led e quando eu voltasse a clicar que me desligasse o led.
Alguem e capaz de modificar esse codigo?
/* * This is a web server that allows you to host a fully functional html * webpage on the World Wide Web. * Initial coding was done with the help from the many people in the Arduino community. * Thanks guys!! * * Arduino Setup: You need an Ethernet Shield SD, and and Arduino. * Optionally pins 8 and 9 can be used for two LEDs that can indicate traffic. * * SD Card Setup: On the SD card, which must be formated as fat, you must have * an HTML file with the file name of 'index.htm'. All file names on this card * must be written in the old 8.3 file format. In other words, all files must be * named with no more then 8 characters for the name, and 3 for the extension. * * Note: If you don't know HTML, a good place that I found useful was w3schools * http://www.w3schools.com/html/html_examples.asp * */ #include <LiquidCrystal.h> #include <SPI.h> #include <SdFat.h> #include <SdFatUtil.h> #include <Ethernet.h> #define BUFSIZ 128 #define greenLEDandBEEP 2 #define redLEDpin 3 boolean led2 = true; int hits = 0; // Set the number of hits the hit counter will start at. int units = 0; int count = 0; int photocellPin = 2; int photocellReading; LiquidCrystal lcd(4, 5, 6, 7, 8, 9); //Local ethernet setup byte mac[] = { 0x90, 0xA2, 0xDA, 0x00, 0x1C, 0x0E }; byte ip[] = { 192, 168, 1, 80 }; char rootFileName[] = "index.htm"; Server server(8080); //SD card stuff Sd2Card card; SdVolume volume; SdFile root; SdFile file; #define error(s) error_P(PSTR(s)) void error_P(const char* str) { PgmPrint("error: "); SerialPrintln_P(str); if (card.errorCode()) { PgmPrint("SD error: "); Serial.print(card.errorCode(), HEX); Serial.print(','); Serial.println(card.errorData(), HEX); } while(1); } void setup() { lcd.begin(16, 2); lcd.print("Web Server v2.00"); lcd.setCursor(0, 1); lcd.print("Hits:"); Serial.begin(9600); pinMode(greenLEDandBEEP, OUTPUT); pinMode(redLEDpin, OUTPUT); PgmPrint("Free RAM: "); Serial.println(FreeRam()); pinMode(10, OUTPUT); digitalWrite(10, HIGH); if (!card.init(SPI_HALF_SPEED, 4)) error("card.init failed!"); if (!volume.init(&card)) error("vol.init failed!"); PgmPrint("Volume is FAT"); Serial.println(volume.fatType(),DEC); Serial.println(); if (!root.openRoot(&volume)) error("openRoot failed"); PgmPrintln("Files found in root:"); root.ls(LS_DATE | LS_SIZE); Serial.println(); PgmPrintln("Files found in all dirs:"); root.ls(LS_R); Serial.println(); PgmPrintln("Done"); Ethernet.begin(mac, ip); server.begin(); } void loop() { if(count >=500) { led2 = !led2; digitalWrite(redLEDpin, led2); count = 0; } count +=1; char clientline[BUFSIZ]; char *filename; int image = 0; int index = 0; Client client = server.available(); if (client) { boolean current_line_is_blank = true; index = 0; while (client.connected()) { if (client.available()) { char c = client.read(); if (c != '\n' && c != '\r') { clientline[index] = c; index++; if (index >= BUFSIZ) index = BUFSIZ -1; continue; } clientline[index] = 0; filename = 0; Serial.println(clientline); if (strstr(clientline, "GET / ") != 0) { filename = rootFileName; } if (strstr(clientline, "GET /") != 0) { if (!filename) filename = clientline + 5; (strstr(clientline, " HTTP"))[0] = 0; Serial.println(filename); if (! file.open(&root, filename, O_READ)) { client.println("HTTP/1.1 404 Not Found"); client.println("Content-Type: text/html"); client.println(); client.println("<h2>Error 404</h2>"); client.println("<s2>The file does not exist.<s2>"); client.println(""); break; } Serial.println("Opened!"); //File types client.println("HTTP/1.1 200 OK"); if (strstr(filename, ".htm") != 0) client.println("Content-Type: text/html"); else if (strstr(filename, ".css") != 0) client.println("Content-Type: text/css"); else if (strstr(filename, ".png") != 0) client.println("Content-Type: image/png"); else if (strstr(filename, ".jpg") != 0) client.println("Content-Type: image/jpeg"); else if (strstr(filename, ".gif") != 0) client.println("Content-Type: image/gif"); else if (strstr(filename, ".3gp") != 0) client.println("Content-Type: video/mpeg"); else if (strstr(filename, ".pdf") != 0) client.println("Content-Type: application/pdf"); else if (strstr(filename, ".js") != 0) client.println("Content-Type: application/x-javascript"); else if (strstr(filename, ".xml") != 0) client.println("Content-Type: application/xml"); else client.println("Content-Type: text"); client.println(); int16_t c; while ((c = file.read()) >= 0) { //Serial.print((char)c); //Prints all HTML code to serial (For debuging) client.print((char)c); //Prints all HTML code for web page } //Hit counter math if(units >= 2) { hits ++; units = 0; } units +=1; //End hit counter math //Print the hit counters and light value lcd.setCursor(6, 1); lcd.print(hits); //Print hits for LCD hit counter client.print("<html><body>"); //HTML code starts here client.print("<P align=\"center\">"); client.print("Hits since reset: <b>"); client.print(hits); //Print hits to client client.print("</b><br>"); photocellReading = analogRead(photocellPin); client.print("Light reading: "); client.print(photocellReading); //Prints light reading to client // A few threshholds if (photocellReading < 10) { client.print(" - Dark"); } else if (photocellReading < 200) { client.print(" - Dim"); } else if (photocellReading < 500) { client.print(" - Light"); } else if (photocellReading < 800) { client.print(" - Bright"); } else { client.print(" - Very bright"); } client.print("</p></body></html>"); //HTML code ends here //End hit counter and light value file.close(); } else { client.println("HTTP/1.1 404 Not Found"); client.println("Content-Type: text/html"); client.println(); client.println("<h2>Error 404</h2>"); client.println(""); } break; } } digitalWrite(greenLEDandBEEP, HIGH); delay(1); digitalWrite(greenLEDandBEEP, LOW); client.stop(); } } //The End /*
…
poderia me ajudar a entender a sintaxe da parte que eu destaquei em vermelho?
Seria interessante utilizar uma rede MODBUS sem supervisórios em aplicações onde o custo total da instalação é reduzido...
#include <SimpleModbusMaster.h>
/* SimpleModbusMaster allows you to communicate to any slave using the Modbus RTU protocol. To communicate with a slave you need to create a packet that will contain all the information required to communicate to the slave. Information counters are implemented for further diagnostic. These are variables already implemented in a packet. You can set and clear these variables as needed. The following modbus information counters are implemented: requests - contains the total requests to a slave successful_requests - contains the total successful requests failed_requests - general frame errors, checksum failures and buffer failures retries - contains the number of retries exception_errors - contains the specific modbus exception response count These are normally illegal function, illegal address, illegal data value or a miscellaneous error response. And finally there is a variable called "connection" that at any given moment contains the current connection status of the packet. If true then the connection is active. If false then communication will be stopped on this packet until the programmer sets the connection variable to true explicitly. The reason for this is because of the time out involved in modbus communication. Each faulty slave that's not communicating will slow down communication on the line with the time out value. E.g. Using a time out of 1500ms, if you have 10 slaves and 9 of them stops communicating the latency burden placed on communication will be 1500ms * 9 = 13,5 seconds! Communication will automatically be stopped after the retry count expires on each specific packet. All the error checking, updating and communication multitasking takes place in the background. In general to communicate with to a slave using modbus RTU you will request information using the specific slave id, the function request, the starting address and lastly the number of registers to request. Function 3, 4 & 16 are supported. In addition to this broadcasting (id = 0) is supported for function 16. Constants are provided for: Function 3 - READ_HOLDING_REGISTERS Function 4 - READ_INPUT_REGISTERS Function 16 - PRESET_MULTIPLE_REGISTERS Note: The Arduino serial ring buffer is 128 bytes or 64 registers. Most of the time you will connect the Arduino using a MAX485 or similar. In a function 3 or 4 request the master will attempt to read from a slave and since 5 bytes is already used for ID, FUNCTION, NO OF BYTES and two BYTES CRC the master can only request 122 bytes or 61 registers. In a function 16 request the master will attempt to write to a slave and since 9 bytes is already used for ID, FUNCTION, ADDRESS, NO OF REGISTERS, NO OF BYTES and two BYTES CRC the master can only write 118 bytes or 59 registers. Note: Using a USB to Serial converter the maximum bytes you can send is limited to its internal buffer which differs between manufactures. Since it is assumed that you will mostly use the Arduino to connect without using a USB to Serial converter the internal buffer is set the same as the Arduino Serial ring buffer which is 128 bytes.*/
//////////////////// Port information ///////////////////#define baud 9600#define timeout 1000#define polling 200 // the scan rate
// If the packets internal retry register matches// the set retry count then communication is stopped// on that packet. To re-enable the packet you must// set the "connection" variable to true.#define retry_count 5
// used to toggle the receive/transmit pin on the driver#define TxEnablePin 2
// This is the easiest way to create new packets// Add as many as you want. TOTAL_NO_OF_PACKETS// is automatically updated.enum{ PACKET1, PACKET2, // leave this last entry TOTAL_NO_OF_PACKETS};
// Create an array of Packets to be configuredPacket packets[TOTAL_NO_OF_PACKETS];
// Create a packetPointer to access each packet// individually. This is not required you can access// the array explicitly. E.g. packets[PACKET1].id = 2;// This does become tedious though...packetPointer packet1 = &packets[PACKET1];packetPointer packet2 = &packets[PACKET2];
// The data from the PLC will be stored in the regs arrayunsigned int regs[10];
void setup(){ // The modbus packet constructor function will initialize // the individual packet with the assigned parameters. You can always do this // explicitly by using struct pointers. The first parameter is the address of the // packet in question. It is effectively the "this" parameter in Java that points to // the address of the passed object. It has the following form: // modbus_construct(packet, id, function, address, number of registers, register array) // read 2 registers starting at address 0 modbus_construct(packet1, 2, READ_HOLDING_REGISTERS, 0, 2, regs); // write the 10 registers to the PLC starting at address 2 modbus_construct(packet2, 2, PRESET_MULTIPLE_REGISTERS, 2, 10, regs); // P.S. the register array entries above can be different arrays // Initialize communication settings etc... modbus_configure(baud, timeout, polling, retry_count, TxEnablePin, packets, TOTAL_NO_OF_PACKETS);}
void loop(){ modbus_update();
// update the array with the counter data regs[2] = packet1->requests; regs[3] = packet1->successful_requests; regs[4] = packet1->failed_requests; regs[5] = packet1->exception_errors; regs[6] = packet2->requests; regs[7] = packet2->successful_requests; regs[8] = packet2->failed_requests; regs[9] = packet2->exception_errors;
}…
controlo por potenciômetro e quando chego no angulo q eu quero aperto um botão na placa shield e ele grava na eprom esse valor e vou fazendo ate pegar o objeto e levar para outro lugar, quando termino aperto outro botão que repeti os movimentos que gravei e tá funcionando só que ele repeti 4x de boa depois ele perde um movimento e começa a fazer movimentos que não havia gravado, gostaria de saber pq acontece depois da quarta repetição! alguem pode me ajudar não manjo de programação e não sei se o código esta correto,!
Placa Shield
Programação do Braço Robótico
#include <Servo.h> #include <EEPROM.h> // Biblioteca
Servo Garra; Servo Ggarra; Servo Lgarra; Servo Cotovelo; Servo Ombro; Servo Base; int buzzer = 7; int state = LOW; int state1 = LOW; int button = 3; int button1 = 2; int potgarra = 0; //Canal Analógico A0 int potggarra = 1; //Canal Analógico A1 int potlgarra = 2; //Canal Analógico A2 int potombro = 3; //Canal Analógico A3 int potcot = 4; //Canal Analógico A4 int potbase = 5; //Canal Analógico A5 int valbase; // Constante p/ valor do ângulo servomotor Base int valombro; // Constante p/ valor do ângulo servomotor Ombro int valcot; // Constante p/ valor do ângulo servomotor Cotovelo int valgarra; // Constante p/ valor do ângulo servomotor Garra int valggarra; // Constante p/ valor do ângulo servomotor Giro da Garra int vallgarra; // Constante p/ valor do ângulo servomotor Levantar Garra int addr = 0; // Endereço de escrita na memória int cont; int address = 0; // endereço de leitura na memória byte value; // valor lido da EEPROM
void setup() { pinMode(button, INPUT); pinMode(button1, INPUT); pinMode(buzzer, OUTPUT); Garra.attach(13); Ggarra.attach(12); Lgarra.attach(11); Ombro.attach(10); Cotovelo.attach(9); Base.attach(8); Serial.begin(9600); } void loop(){ state=digitalRead(button); // Se o botão for pressionado grava a posição dos servos if(state==HIGH){ digitalWrite(buzzer, HIGH); //Liga sinal de aviso do buzzer delay(100); digitalWrite(buzzer, LOW); //desliga sinal de aviso do buzzer delay(100); valbase= analogRead(potbase); // Lê e o valor do potenciometro valbase= map(valbase, 0, 1023, 0, 179); // Converte o valor lido p/ respetiva referência entre (0° a 180°) EEPROM.write(addr, valbase); // Grava o valor lido na EEPROM Serial.print(addr); //Printa o endereço e os respectivos ângulos para cada servomotor Serial.println(" - Endereço"); Serial.println("Base"); Serial.println(valbase); addr = addr + 1; //Incremento p/ o proximo endereço delay(100);
valombro= analogRead(potombro); // valombro= map(valombro, 0, 1023, 53, 90); EEPROM.write(addr, valombro); Serial.print(addr); Serial.println(" - Endereço"); Serial.println("Ombro"); Serial.println(valombro); addr = addr + 1; delay(100);
valcot = analogRead(potcot); valcot = map(valcot, 0, 1023, 48, 158); EEPROM.write(addr, valcot); Serial.print(addr); Serial.println(" - Endereço"); Serial.println("Cotovelo"); Serial.println(valcot); addr = addr + 1; delay(100);
valgarra= analogRead(potgarra); valgarra= map(valgarra, 0, 1023, 34, 110); EEPROM.write(addr, valgarra); Serial.print(addr); Serial.println(" - Endereço"); Serial.println("Garra"); Serial.println(valgarra); addr = addr + 1; delay(100); valggarra= analogRead(potggarra); // valggarra= map(valgarra, 0, 1023, 0, 179); EEPROM.write(addr, valggarra); Serial.print(addr); Serial.println(" - Endereço"); Serial.println("Ggarra"); Serial.println(valggarra); addr = addr + 1; delay(100);
vallgarra= analogRead(potlgarra); // vallgarra= map(valgarra, 0, 1023, 5, 90); EEPROM.write(addr, vallgarra); Serial.print(addr); Serial.println(" - Endereço"); Serial.println("Lgarra"); Serial.println(vallgarra); addr = addr + 1; delay(100);
if (addr == 1024){ // Aviso para limite de posições salvas na EEPROM delay(10); digitalWrite(buzzer, HIGH); delay(10); digitalWrite(buzzer, LOW); delay(10); digitalWrite(buzzer, HIGH); delay(10); digitalWrite(buzzer, LOW); delay(10); } } else { //leitura do analogico valbase= analogRead(potbase); //Lê o valor do potenciometro de ( 0 - 1023) valbase= map(valbase, 0, 1023, 0, 179); //converte o valor lido de ( 0 - 1023) p/ (0 °– 180°) Base.write(valbase);
valombro = analogRead(potombro); valombro = map(valombro, 0, 1023, 53, 90); Ombro.write(valombro);
valcot = analogRead(potcot); valcot = map(valcot, 0, 1023, 48, 158); Cotovelo.write(valcot);
valgarra = analogRead(potgarra); valgarra = map(valgarra, 0, 1023, 34, 110); Garra.write(valggarra);
valggarra = analogRead(potggarra); valggarra = map(valggarra, 0, 1023, 0, 179); Ggarra.write(valggarra);
vallgarra = analogRead(potlgarra); vallgarra = map(vallgarra, 0, 1023, 5, 90); Lgarra.write(vallgarra);
} state1=digitalRead(button1); // Botão p/ acionamento das movimentações gravadas if(state1==HIGH){ digitalWrite(buzzer, HIGH); delay(100); digitalWrite(buzzer, LOW); delay(100); digitalWrite(buzzer, HIGH); delay(100); digitalWrite(buzzer, LOW); delay(100); Play(); //Chamada da função p/ movimentar } } void movServo(Servo &s, int ANGfinal, int veloc){ int ANGinicial = s.read(); // lê a posição atual do servo e o coloca como o angulo inicial de movimento if(ANGinicial > ANGfinal){ for(int i= ANGinicial; i > ANGfinal; i--){ //decremanta 1º grau s.write(i); // 'escreve' o valor 'i' no servo selecionado delay(veloc); // tempo de espera. } } else{ for(int i= ANGinicial; i <= ANGfinal; i++){ //incremanta 1º grau s.write(i); // 'escreve' o valor 'i' no servo selecionado delay(veloc); // tempo de espera. } } } void Play(){ // Função de movimento automático dos servos delay(1000); state1=digitalRead(button1); while(state1==LOW){ state1=digitalRead(button1); if(state1==HIGH){ zerar(); delay(100); } int l; LDR=0; //Zera a variável LDR for(l=0;l<10;l++){ //Faz 10 vezes a leitura do sensor cont=analogRead(sensor); //Lê o valor do sensor e guarda na variável LDR LDR = LDR+cont; //Armazenamento na varíavel LDR o valor lido + o valor anterior delay(10); //Delay se 10 milissegundos } LDR=LDR/10; //Divide o valor armazenado por 10 Serial.println(LDR); //Imprime o valor do LDR
if(LDR > 80){ // Se o valor do LDR for maior ou igual a 400 movServo(Base, valbase, 15); movServo(Ombro, valombro, 15); movServo(Cotovelo, valcot, 15); movServo(Garra, valgarra, 15); Serial.println("Home Position"); delay(100); } if(LDR < 400){ int j; address=0; addr=addr-1; Serial.println("addr"); Serial.println(addr); for(j=0; j<addr; j+=4){ value = EEPROM.read(address); // Leitura da EEPROM movServo(Base, value, 15); delay(100); Serial.print(address); Serial.println(" - Posicao Base"); Serial.print(value, DEC); Serial.println(); address = address + 1; delay(100); value = EEPROM.read(address); movServo(Ombro, value, 15); delay(100); Serial.print(address); Serial.println(" - Posicao Ombro"); Serial.print(value, DEC); Serial.println(); address = address + 1; delay(100); value = EEPROM.read(address); movServo(Cotovelo, value, 15); delay(100); Serial.print(address); Serial.println(" - Posicao Cotovelo"); Serial.print(value, DEC); Serial.println(); address = address + 1; delay(100); value = EEPROM.read(address); movServo(Garra, value, 15); delay(100); Serial.print(address); Serial.println(" - Posicao Garra"); Serial.print(value, DEC); Serial.println(); delay(100); address = address + 1; value = EEPROM.read(address); movServo(Ggarra, value, 15); delay(100); Serial.print(address); Serial.println(" - Posicao Giro da Garra"); Serial.print(value, DEC); Serial.println(); delay(100); address = address + 1; value = EEPROM.read(address); movServo(Lgarra, value, 15); delay(100); Serial.print(address); Serial.println(" - Posicao Levanta Garra"); Serial.print(value, DEC); Serial.println(); delay(100); address = address + 1; } } } } void zerar(){ // Zera o endereço da EEPROM p/ realizar novas gravações digitalWrite(buzzer, HIGH); // Aviso p/ realizar novas gravações delay(100); digitalWrite(buzzer, LOW); delay(100); digitalWrite(buzzer, HIGH); delay(100); digitalWrite(buzzer, LOW); delay(100); addr=0; Serial.print("Modo Gravar");…
=7;
int led4=6;
int buzzer=10;
Tone player;
int note[]={NOTE_A3,NOTE_G4};
// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
void setup() {
// set up the LCD's number of columns and rows:
Serial.begin(9600);
lcd.begin(16, 2);
// Print a message to the LCD.
lcd.print("Lab de Garagem");
pinMode(led1,OUTPUT);
pinMode(led2,OUTPUT);
pinMode(led3,OUTPUT);
pinMode(led4,OUTPUT);
pinMode(buzzer,OUTPUT);
player.begin(10);
}
void loop() {
int reading = analogRead(sensorPin);
// set the cursor to column 0, line 1
// (note: line 1 is the second row, since counting begins with 0):
lcd.setCursor(0, 1);
// print the number of seconds since reset:
float voltage = (reading) * 5.0;
voltage /= 1024.0;
// print out the voltage
Serial.print(voltage); Serial.println(" volts");
// now print out the temperature
float temperatureC = (voltage - 0.5) * 10 ; //converting from 10 mv per degree wit 500 mV offset
//to degrees ((volatge - 500mV) times 100)
Serial.print(temperatureC);
Serial.println(" degrees C");
lcd.print(temperatureC);
lcd.print(" Celsius");
// now convert to Fahrenheight
float temperatureF = (temperatureC * 9.0 / 5.0) + 32.0;
Serial.print(temperatureF); Serial.println(" degrees F");
if(temperatureC<25)
{
digitalWrite(led1,HIGH);
digitalWrite(led2,LOW);
digitalWrite(led3,LOW);
digitalWrite(led4,LOW);
}
if((temperatureC>=25) && (temperatureC<30))
{
digitalWrite(led1,HIGH);
digitalWrite(led2,HIGH);
digitalWrite(led3,LOW);
digitalWrite(led4,LOW);
}
if((temperatureC>=30) )
{
digitalWrite(led1,HIGH);
digitalWrite(led2,HIGH);
digitalWrite(led3,HIGH);
player.play(note[0]);
delay(200);
player.play(note[1]);
delay(200);
player.stop();
}
delay(500);
}
e está dando erro. Poderiam me ajudar?…
roladora para um sistema de captação e reaproveitamento de aguá de chuva para fins não potáveis em residências. A confecção do hardware está ok, tudo conferido e funcionando corretamente.
Estou trabalhando com dois sensores ultrassônicos HC-SR04, usados para medir o nível de água nos reservatório, variando entre 0 e 100%. e de acordo com os níveis lidos irei acionar uma bomba ou então uma válvula solenoide. O microcontrolador utilizado na placa é um ATmega328P ( o mesmo da plataforma Arduino UNO).
A lógica de programação foi desenvolvida e um êxito na rodagem de testes, no entanto os dados enviados ao display ficam sempre piscando. Eu gostaria de saber o porquê.
Logo abaixo vou deixar algumas fotos para que todos possam ter uma noção mais clara ao que estou me referindo. Abraço e conto com a colaboração de todos.
CÓDIGO:
#include <LiquidCrystal.h> //Biblioteca do display.
#include <LinkedList.h> //
#include <Gaussian.h> //Bibliotecas para cálculo da média móvel.
#include <GaussianAverage.h> //
#include <Ultrasonic.h> //Biblioteca dos sensores ultrassônicos.
#define trigger1 6 //Trigger do US1 no pino 6.
#define echo1 5 //Trigger do US1 no pino 5.
#define trigger2 4 //Trigger do US2 no pino 4.
#define echo2 3 //Trigger do US2 no pino 3.
#define pulsoSOLENOIDE A4 //Botão da solenóde no pino A4.
#define pulsoBOMBA A5 //Botão da bomba no pino A5.
#define AUTO_MANU 0 //Bot. para sel. do modo de trabalho no pino 0.
#define SOLENOIDE 1 //Saída para acionamento da solenóide no pino 1.
#define BOMBA 2 //Saída para acionamento da bomba no pino 2.
LiquidCrystal lcd(12, 11, 10, 9, 8, 7); //Pinos de comu com o display.
GaussianAverage myMovingAverage1(10);
GaussianAverage myMovingAverage2(10);
Ultrasonic ultrasonic1(trigger1, echo1); //Pinos trigger e echo do US1.
Ultrasonic ultrasonic2(trigger2, echo2); //Pinos trigger e echo do US2.
float caixadagua = 28.5; //Caixa d'água com 28,5cm.
float reservatorio = 28.5; //Reservatório com 28,5cm.
int porcentagem1, nivel1, US1; //Variáveis do tipo inteira.
int porcentagem2, nivel2, US2, estadoNivel, setLCD, estadoSolen;
//=========================================================================
void setup(){ //Inícialização do programa.
lcd.begin(20,4); //Define o display com 20 colunas e quatro linhas.
pinMode(pulsoBOMBA,INPUT_PULLUP) //Entrada com pullup interno.
pinMode(pulsoSOLENOIDE,INPUT_PULLUP); //Entrada com pullup interno.
pinMode(AUTO_MANU,INPUT_PULLUP); //Entrada com pullup interno.
pinMode(SOLENOIDE,OUTPUT); //Saída digital.
pinMode(BOMBA,OUTPUT); //Saída digital.
digitalWrite(SOLENOIDE,LOW); //Inicia com a solenóide desligada.
digitalWrite(BOMBA,LOW); //Inicia com a bomba desligada.
estadoNivel = 0; //Atribui valor zero a variável estadoNivel.
estadoSolen = 0; //Atribui valor zero a variável estadoSolen.
} //Fim setup.
//=========================================================================
void loop(){ //Loop do programa.
if(digitalRead(AUTO_MANU) == LOW){ //Cond. que habilita o modo manual.
float cmMsec1;
long microsec1 = ultrasonic1.timing();
cmMsec1 = ultrasonic1.convert(microsec1, Ultrasonic::CM);
porcentagem1 = (((cmMsec1-6.5)*100)/reservatorio);
nivel1 = (100-porcentagem1);
myMovingAverage1 += nivel1;
myMovingAverage1.process();
US1 = myMovingAverage1.mean; //Lógica responsável pela leitura do US1.
if(US1 > 100){
US1 = 100;
}
if(US1 < 0){
US1 = 0;
}
float cmMsec2;
long microsec2 = ultrasonic2.timing();
cmMsec2 = ultrasonic2.convert(microsec2, Ultrasonic::CM);
porcentagem2 = ((cmMsec2-12)*100)/caixadagua;
nivel2 = (100-porcentagem2);
myMovingAverage2 += nivel2;
myMovingAverage2.process();
US2 = myMovingAverage2.mean; //Lógica responsável pela leitura do US2.
if(US2 > 100){
US2 = 100;
}
if(US2 < 0){
US2 = 0;
}
lcd.clear(); //limpa a tela do display.
lcd.setCursor(4,0);
lcd.print("MODO MANUAL"); //Imprime na coluna quatro, linha zero.
lcd.setCursor(0,1);
lcd.print("RESERVATORIO = "); //Imprime na coluna zero linha um.
lcd.setCursor(15,1);
lcd.print(US1); //Impr. US1 na coluna quinze, linha um.
lcd.setCursor(18,1);
lcd.print("%"); //Impr. % na coluna dezoito, linha um.
lcd.setCursor(0,2);
lcd.print("CAIXA D'AGUA = "); //Imprime na coluna zero, linha dois.
lcd.setCursor(15,2);
lcd.print(US2); //Impr. US2 na coluna , linha dois.
lcd.setCursor(18,2);
lcd.print("%"); //Impr. % na coluna dezoito,linha dois.
if(digitalRead(pulsoSOLENOIDE) == LOW){
digitalWrite(SOLENOIDE, HIGH); //Aciona a solenóide.
lcd.setCursor(0,3);
lcd.print("SOLEN=ON"); //Imprime ON na coluna zero, linha 3.
}
else{
digitalWrite(SOLENOIDE, LOW); //Desaciona a solenóide.
lcd.setCursor(0,3);
lcd.print("SOLEN=OFF"); //Impr OFF na coluna zero, linha três.
}
if(digitalRead(pulsoBOMBA) == LOW){
digitalWrite(BOMBA, HIGH); //Aciona a bomba.
lcd.setCursor(10,3);
lcd.print("BOMBA=ON"); //Imprime ON na coluna dez, linha três.
}
else{
digitalWrite(BOMBA, LOW); //Desaciona a bomba.
lcd.setCursor(10,3);
lcd.print("BOMBA=OFF"); //Imprime OFF na coluna dez, linha três.
}
} //Fim manual.
//========================================================================
if(digitalRead(AUTO_MANU) == HIGH){ //Cond. que habilita o modo automát.
float cmMsec1;
long microsec1 = ultrasonic1.timing();
cmMsec1 = ultrasonic1.convert(microsec1, Ultrasonic::CM);
porcentagem1 = (((cmMsec1-6.5)*100)/reservatorio);
nivel1 = (100-porcentagem1);
myMovingAverage1 += nivel1;
myMovingAverage1.process();
US1 = myMovingAverage1.mean; //Lógica responsável pela leitura do US1.
if(US1 > 100){
US1 = 100;
}
if(US1 < 0){
US1 = 0;
}
float cmMsec2;
long microsec2 = ultrasonic2.timing();
cmMsec2 = ultrasonic2.convert(microsec2, Ultrasonic::CM);
porcentagem2 = ((cmMsec2-12)*100)/caixadagua;
nivel2 = (100-porcentagem2);
myMovingAverage2 += nivel2;
myMovingAverage2.process();
US2 = myMovingAverage2.mean; //Lógica responsável pela leitura do US2.
if(US2 > 100){
US2 = 100;
}
if(US2 < 0){
US2 = 0;
}
lcd.clear(); //limpa a tela do display
lcd.setCursor(2,0);
lcd.print("MODO AUTOMATICO"); //Imprimme na coluna dois, linha zero.
lcd.setCursor(0,1);
lcd.print("RESERVATORIO = "); //Imprime na coluna zero, linha um.
lcd.setCursor(15,1);
lcd.print(US1); //Imp. US1 na coluna quinze, linha um.
lcd.setCursor(18,1);
lcd.print("%"); //Impr. % na coluna dezoito, linha um.
lcd.setCursor(0,2);
lcd.print("CAIXA D'AGUA = "); //Imprime na coluna zero, linha dois.
lcd.setCursor(15,2);
lcd.print(US2); //Imp. US2 coluna quinze, linha dois.
lcd.setCursor(18,2);
lcd.print("%"); //Impri. % coluna dezoito, linha dois.
switch(estadoNivel){ //Switch responsável pelo controle da bomba.
case 0:
estadoNivel = 1; //Atribui valor um à variável estadoNivel.
if((US2 < 20) && (US1 >10)){ //Se US2>20% e US1>10%.
digitalWrite(BOMBA, HIGH); //Aciona a bomba.
}
break;
case 1:
estadoNivel = 2; //Atribui valor dois a var. estadoNivel.
if(US2 > 90){ //Habilita se US2>90%.
digitalWrite(BOMBA, LOW); //Desaciona a bomba.
setLCD = 0;
}
break;
case 2:
estadoNivel = 0; //Atribui valor zero à var. estadoNivel.
if(US1 < 10){ //Habilita se US1<10%.
digitalWrite(BOMBA, LOW); //Desaciona a bomba.
setLCD = 0;
}
break;
}
if (digitalRead(BOMBA) == LOW){ //Se a bomba estiver desligada.
lcd.setCursor(10,3);
lcd.print("BOMBA=OFF"); //Imprime na coluna zero, linha três.
}
else{
lcd.setCursor(10,3);
lcd.print("BOMBA=ON"); //Imprime na coluna dez, linha três.
}
switch(estadoSolen){ //Switch responsável pelo controle da solenóide.
case 0:
//Atribui valor um a var. estadoSolen.
if((US2 <20) && (US1 < 10)){ //Se US2> 20% e US1<20%.
digitalWrite(SOLENOIDE, HIGH); //Aciona solenóide.
}
break;
case 1:
estadoSolen = 0; //Atribui valor zero a var. estadoSolen.
if(US2 > 90){ //Se US2>90%.
digitalWrite(SOLENOIDE, LOW); //Desaciona a solenóide.
}
break;
}
if (digitalRead(SOLENOIDE) == LOW){ //Se a sol. estiver desligada.
lcd.setCursor(0,3);
lcd.print("SOLEN=OFF"); //Imprime na coluna zero, linha três.
}
else{
lcd.setCursor(0,3);
lcd.print("SOLEN=ON"); //Imprime na coluna zero, linha três.
}
}
delay(500);
} //Fim loop.
…