lude <SPI.h>#include <Ethernet.h>//PINOS UTILIZADOS (SAIDA)int saidaLuz = 13; //PINO DAS LUZESint saidaTv = 5; //PINO DA TB//PINOS UTILIZADOS (VOLTA)int botaoLuz = 32;//ESTADO DO APARELHOS ( PINOS )boolean estadoLuz = false;boolean estadoTV = false;// MAC E IP DO ARDUINObyte mac[] = { 0x00, 0xAA, 0xBB, 0xCC, 0xDE, 0x02};IPAddress ip(192, 168, 1, 3);//INICIA O SERVER NA PORTA 80EthernetServer server(80);void setup() { //PINOS DE SAIDA pinMode(saidaLuz,OUTPUT); pinMode(saidaTv,OUTPUT); //PINOS DE ENTRADA pinMode(botaoLuz,INPUT); //AGUARDA CONEXAO SERIAL Serial.begin(9600); while (!Serial) {;} //INICIA O SERVIDOR; Ethernet.begin(mac,ip); server.begin(); Serial.print("server is at "); Serial.println(Ethernet.localIP());}void loop() {if(digitalRead(botaoLuz) == HIGH || estadoLuz == true){ digitalWrite(saidaLuz,HIGH); estadoLuz = true; }else if(digitalRead(botaoLuz) == LOW || estadoLuz == false){ digitalWrite(saidaLuz,LOW); delay(1000); estadoLuz = false; }// listen for incoming clients EthernetClient client = server.available(); if (client) { // an http request ends with a blank line boolean currentLineIsBlank = true; while (client.connected()) { if (client.available()) { char c = client.read(); Serial.println(c); // if you've gotten to the end of the line (received a newline // character) and the line is blank, the http request has ended, // so you can send a reply if (c == '\n' && currentLineIsBlank) { // send a standard http response header client.println("HTTP/1.1 200 OK"); client.println("Content-Type: text/html"); client.println("Connection: close"); // the connection will be closed after completion of the response client.println(); client.println("<!DOCTYPE HTML>"); client.println("<html>");client.println("<head>");client.println("<title>Automação Residencial</title>");client.println("<link rel=\"stylesheet\" href=\"botoes.css\" type=\"text/css\" />");client.println("<style>");client.println("@font-face { font-family: Century; src: url('GOTHIC.ttf');}");client.println("body{font-family: Century; background: rgb(51,51,51); padding:20px;}");client.println("*{ color:rgb(255,255,255);}");/*INICIO DA CONFIGURAÇÃO DOS RETANGULOS*/client.println(".tile img{ width:56px; margin:20px 22px 0 22px;}");client.println(".tileLargo img { margin:20px 77px 0 77px;}");client.println(".tile{ height:100px; width:100%; text-align:center; float:left; margin-top:5px;}");client.println(".amarelo{ background:#DAA520;}");client.println(".vermelho{ background:#CD0000;}");client.println(".azul{ background:#4682B4;}");client.println(".verde{background-color: #2E8B57;}");client.println(".selecionado{ background-color: #483D8B;}");/*FIM DA CONFIGURAÇÃO DOS RETANGULOS*//*INICIO DAS CONFIGURAÇÕES DOS COMODOS*/client.println(".comodos{ position:absolute; top:0; left:0; background:RGBA(0,0,0,0,1); width:100%; height:auto;}");client.println(".tabelas{ width:100%; text-align:center;}");client.println(".comodosOpen{ width:100%; height:30px; line-height:30px; text-align:center; background:RGBA(255,255,255,1); margin-top:5px; color:RGBA(0,0,0,1);}");/*FIM DACONFIGURAÇÃO DOS COMODOS*/client.println("</style>");client.println("<script language=\"javascript\" src=\"jquery.js\"></script>");client.println("<script language=\"javascript\">");client.println("$(document).ready(function(e) {");client.println("$(\"#sala\").hide();");client.println("$(\"#cozinha\").hide();");client.println("});");client.println("function mostraJanela(local){");client.println("$(\"#\"+local).show();");client.println("$(\"#\"+local+\" #close\").click(function(){");client.println("$(\"#\"+local).hide();");client.println("});");client.println("}");client.println("function fazFuncao(endereco){");client.println("window.location(endereco);");client.println("alert(endereco);");client.println("}");client.println("</script>");client.println("</head>");client.println("<body>");client.println("<h1 align=\"center\">Automação Residêncial</h1>");client.println("<a href=\"#\" onClick=\"mostraJanela('sala');\">");client.println("<div class=\"tile amarelo\">");client.println("<img src=\"imagens/sala.png\" alt=\"Sala\"/>");client.println("<span>Sala</span></div>");client.println("</a>");client.println("<a href=\"#\" onClick=\"mostraJanela('cozinha');\">");client.println("<div class=\"tile azul\">");client.println("<img src=\"imagens/imgCozinha.png\" alt=\"Cozinha\"/>");client.println("<span>Cozinha</span></div>");client.println("</a>");client.println("<a href=\"#\">");client.println("<div class=\"tile vermelho\">");client.println("<img src=\"imagens/quarto.png\" alt=\"Quarto\" />");client.println("<span>Quartos</span></div>");client.println("</a>");client.println("<a href=\"#\">");client.println("<div class=\"tile verde\">");client.println("<img src=\"imagens/piscina.png\" alt=\"Piscina\" />");client.println("<span>Piscina</span></div>");client.println("</a>");client.println("<a href=\"#\">");client.println("<div class=\"tile amarelo\">");client.println("<img src=\"imagens/churrasqueira.png\" alt=\"Churrasqueira\" />");client.println("<span>Churrasqueira</span></div>"); client.println("</div>");client.println("</a>");//INICIO DAS DIVS DO COMODO DA SALAclient.println("<div id=\"sala\" class=\"comodos\">");client.println("<a href=\"#\" id=\"close\">Fechar Janela</a>");//Luzes Salaclient.println("<div id=\"luzSala\" class=\"comodosOpen\">");client.println("Luzes da Sala:");client.println("<label class=\"switch switch-green\">");client.println("<input type=\"checkbox\" onchange=\"fazFuncao('http://192.168.0.1/luzes');\" class=\"switch-input\">");client.println("<span class=\"switch-label\" data-on=\"On\" data-off=\"Off\"></span>");client.println("<span class=\"switch-handle\"></span>");client.println("</label>");client.println("</div>");//Som da Salaclient.println("<div id=\"somSala\" class=\"comodosOpen\">");client.println("Som da Sala:");client.println("<label class=\"switch switch-green\">");client.println("<input type=\"checkbox\" onchange=\"fazFuncao('http://192.168.0.1/som');\" class=\"switch-input\">");client.println("<span class=\"switch-label\" data-on=\"On\" data-off=\"Off\"></span>");client.println("<span class=\"switch-handle\"></span>");client.println("</label>");client.println("</div>");//Tv da Salaclient.println("<div id=\"tvSala\" class=\"comodosOpen\">");client.println("Tv da Sala:");client.println("<label class=\"switch switch-green\">");client.println("<input type=\"checkbox\" onchange=\"fazFuncao('http://192.168.0.1/tv')\" class=\"switch-input\">");client.println("<span class=\"switch-label\" data-on=\"On\" data-off=\"Off\"></span>");client.println("<span class=\"switch-handle\"></span>");client.println("</label>");client.println("</div>");client.println("</div>");/*FIM DAS DIVS DOS COMODOS*/if(estadoLuz == true){client.println("<label class=\"switch switch-green\">");client.println("<input type=\"checkbox\" onchange=\"fazFuncao(\'http://192.168.1.3/apagarLuz\')\" class=\"switch-input\" checked=\"checked\">");client.println("<span class=\"switch-label\" data-on=\"On\" data-off=\"Off\"></span>");client.println("<span class=\"switch-handle\"></span>");client.println("</label>");}else{client.println("<label class=\"switch switch-green\">");client.println("<input type=\"checkbox\" onchange=\"fazFuncao(\'http://192.168.1.3/acenderLuz\')\" class=\"switch-input\">");client.println("<span class=\"switch-label\" data-on=\"On\" data-off=\"Off\"></span>");client.println("<span class=\"switch-handle\"></span>");client.println("</label>");}client.println("</body>");client.println("</html>"); break;} if (c == '\n') { // you're starting a new line currentLineIsBlank = true; } else if (c != '\r') { // you've gotten a character on the current line currentLineIsBlank = false; } } } // give the web browser time to receive the data delay(1); // close the connection: client.stop(); }}…
ados provenientes da leitura de temperatura são salvos no cartao SD através da shield data loggin
O problema que vem apresentando é o seguinte, os dados da temperatura no LCD demoram a atualizar, quando o valor da temperatura se altera o visor meio que reseta, a temperatura some e depois volta a aparecer com o valor atualizado. Alguem poderia me ajudar ?
Desde já agradeço segue o código o qual também sera anexado
-----------------------------------------------------------------------
#include <LiquidCrystal_I2C.h>#include <SPI.h>#include <SD.h>#include "RTClib.h"#include <OneWire.h> //BIBLIOTECA NECESSÁRIA PARA O DS18B20#include <DallasTemperature.h> //BIBLIOTECA NECESSÁRIA PARA O DS18B20#include <SoftwareSerial.h>#define DS18B20 7 //DEFINE O PINO DO SENSOR DS18B20
//***************************DS18b20**************OneWire ourWire(DS18B20);//CONFIGURA UMA INSTÂNCIA ONEWIRE PARA SE COMUNICAR COM DS18B20DallasTemperature sensors(&ourWire); //PASSA A TEMPERATURA PARA O DallasTemperature//************************************************
// declarando vairáveis para tempo #define intervalo_SMS 237 // intervalo de tempo entre SMS, em minutosstatic unsigned long ref_Tempo = 0;#define periodo_SMS_ms (unsigned long)1000*60*intervalo_SMS//***************************
const int chipSelect = 53;// CS do cartão de memóriafloat sensor1 = 0; // Variável para o sensor 1
byte vccPin = 3;byte gndPin = 2;
SoftwareSerial SIM900(10,11); // Mega 10 e 11 RTC_DS1307 rtc;//PARA RTC PIN 4 SDA20 PIN 5 SCL 21
// MOSI - pin 11 para 51 no Arduino Mega 2560 // MISO - pin 12 para 50 no Arduino Mega 2560// CLK - pin 13 para 52 no Arduino Mega 2560 // CS - pin 10 para 53 no Arduino Mega 2560
// Declaração dos pinos do LCD LiquidCrystal_I2C lcd(0x27, 16, 2);
// Declara dataFile como arquivo para salvar no SDFile dataFile;
// Gera um simbolo de grausuint8_t degree[8] = {140, 146, 146, 140, 128, 128, 128, 128};
// Protótipo de funçõesbyte SPIRead(void);void storeSD();
void setup() { sensors.begin();SIM900.begin(19200); Serial.begin(19200); delay(1000); pinMode(vccPin, OUTPUT); digitalWrite(vccPin, HIGH); pinMode(gndPin, OUTPUT); digitalWrite(gndPin, LOW); Serial.begin(9600);
lcd.begin(); lcd.createChar(0, degree); lcd.setCursor(0, 0); lcd.print("Inicializando..."); delay(1000);
// Confere se o cartão está presente e operante if (!SD.begin(53)) { lcd.setCursor(0, 0); lcd.print("Falha no cartao "); return; } lcd.setCursor(0, 0); lcd.print("Cartao OK "); delay(500);
//valida a inicialização if (!rtc.begin()){ Serial.println("RTC not found!"); while (1); //fica aqui pra sempre } if (!rtc.isrunning()){ Serial.println("RTC is not working!"); rtc.adjust(DateTime(F(__DATE__), F(__TIME__))); //Ajuste de data e hora na compilação, pela substituição das macros}}void loop() { lcd.clear(); // Limpa o display
// Linha 0, coluna 0 lcd.setCursor(0, 0); sensors.requestTemperatures(); sensor1 = sensors.getTempCByIndex(0); lcd.print("Temperatura"); lcd.setCursor(0,1); lcd.print(sensor1, 1); lcd.write((byte)0); lcd.print("C");
if(sensor1 < 2 || sensor1 > 6) {
sendSMS(); delay(60000); }// *****************************************// ENVIANDO SMS EM PRERIODO DE TEMPO//****************************************** static unsigned long ref_Tempo = 0;
if (sensor1 > 2 || sensor1 < 6){ if( ( millis() - ref_Tempo ) >= periodo_SMS_ms){ sendSMSCONTROLE(); // envia o SMS via modulo GSM.
ref_Tempo = millis(); // nova referencia de tempo para o proximo SMS.}}
storeSD(); // Função que faz o armazenamento das leituras no SD delay(10000); // Aguarda 10 Segundos para uma nova leitura e armazenamento no cartão}
/**************************************************************************************/// Função para armazenamento dos dados de leitura feitos anteriormente/**************************************************************************************/void storeSD() {
DateTime now = rtc.now(); // Formata os dados para serem salvos no Cartão SD a cada 1 segundo String dataString = ""; // Declara uma string para salvar os dados no SD dataString += now.day(); dataString += "/" ; dataString += now.month(); dataString += "/" ; dataString += now.year(); dataString += "\t" ; dataString += now.hour(); dataString += ":" ; dataString += now.minute(); dataString += ":" ; dataString += now.second(); dataString += "\t" ; dataString += String(sensor1); // Valor da leitura do sensor 1 dataString += " °C "; dataString += "\t" ; dataString += "ENGEMATe: Unidade teste"; //EMPRESA
// Abre o arquivo, escreve e o fecha novamente dataFile = SD.open("datalog.txt", FILE_WRITE);
// Se o arquivo esta presente, escreve no mesmo if (dataFile) { dataFile.println(dataString); dataFile.close(); } // Se o arquivo não abrir, indica no display else { lcd.setCursor(0, 0); lcd.print("Falha ao abrir "); lcd.setCursor(0, 1); lcd.print("o arquivo no SD "); }}
void sendSMS() {//Serial.println("Sending SMS..."); SIM900.print("AT+CMGF=1\r"); //Configure text mode to send or receive SMS delay(1000); SIM900.println("AT+CMGS=\"+5562981964152\""); //NUMERO DO DETINATÁRIO delay(1000); SIM900.println(String(F("ENGEMATe informa unidade Albert Sabin: FORA DA FAIXA DE TOLERANCIA, temperatura em graus celcius :")) + String( sensor1 ) + String(F("*C"))); //TEXTO MENSAGEM delay(100); SIM900.println((char)26); //End command ^Z delay(100); SIM900.println(); delay(5000);
//Serial.println("Sending SMS..."); SIM900.print("AT+CMGF=1\r"); //Configure text mode to send or receive SMS delay(1000); SIM900.println("AT+CMGS=\"981224345\""); //NUMERO DO DESTINATÁRIO delay(1000); SIM900.println(String(F("ENGEMATe informa unidade Albert Sabin: FORA DA FAIXA DE TOLERANCIA, temperatura em graus celcius :")) + String( sensor1 )+ String(F("*C"))); //TEXTO MENSAGEM delay(100); SIM900.println((char)26); //End command ^Z delay(100); SIM900.println(); delay(5000);
//Serial.println("Sending SMS..."); SIM900.print("AT+CMGF=1\r"); //Configure text mode to send or receive SMS delay(1000); SIM900.println("AT+CMGS=\"984419811\""); //NUMERO DO DESTINATÁRIO delay(1000); SIM900.println(String(F("ENGEMATe informa unidade Albert Sabin: FORA DA FAIXA DE TOLERANCIA, temperatura em graus celcius :")) + String( sensor1 )+ String(F("*C"))); //TEXTO MENSAGEM delay(100); SIM900.println((char)26); //End command ^Z delay(100); SIM900.println(); delay(5000); }void sendSMSCONTROLE() {//Serial.println("Sending SMS..."); SIM900.print("AT+CMGF=1\r"); //Configure text mode to send or receive SMS delay(1000); SIM900.println("AT+CMGS=\"+5562981964152\""); //NUMERO DO DETINATÁRIO delay(1000); SIM900.println(String(F("ENGEMATe informa unidade Albert Sabin: FUNCIONANDO, temperatura = ")) + String( sensor1 ) + String(F("*C"))); //TEXTO MENSAGEM delay(100); SIM900.println((char)26); //End command ^Z delay(100); SIM900.println(); delay(5000);
//Serial.println("Sending SMS..."); SIM900.print("AT+CMGF=1\r"); //Configure text mode to send or receive SMS delay(1000); SIM900.println("AT+CMGS=\"981224345\""); //NUMERO DO DESTINATÁRIO delay(1000); SIM900.println(String(F("ENGEMATe informa unidade Albert Sabin: FUNCIONANDO, temperatura = ")) + String( sensor1 ) + String(F("*C"))); //TEXTO MENSAGEM delay(100); SIM900.println((char)26); //End command ^Z delay(100); SIM900.println(); delay(5000);
//Serial.println("Sending SMS..."); SIM900.print("AT+CMGF=1\r"); //Configure text mode to send or receive SMS delay(1000); SIM900.println("AT+CMGS=\"984419811\""); //NUMERO DO DESTINATÁRIO delay(1000); SIM900.println(String(F("ENGEMATe informa unidade Albert Sabin: FUNCIONANDO, temperatura = ")) + String( sensor1 ) + String(F("*C"))); //TEXTO MENSAGEM delay(100); SIM900.println((char)26); //End command ^Z delay(100); SIM900.println(); delay(5000); }…
ero mas não envia via sms com o link.Peguei o código e fui modificando , incluindo algumas coisas para me ajudar.
O código é esse :
#include <SPI.h> #include <SD.h> #include <TinyGPS++.h> #define ARDUINO_USD_CS 8 // uSD card CS pin (pin 8 on Duinopeak GPS Logger Shield)
String avalia = ""; int conta = 0;
///////////////////////// // Log File Defintions // ///////////////////////// // Keep in mind, the SD library has max file name lengths of 8.3 - 8 char prefix, // and a 3 char suffix. // Our log files are called "gpslogXX.csv, so "gpslog99.csv" is our max file. #define LOG_FILE_PREFIX "gpslog" // Name of the log file. #define MAX_LOG_FILES 100 // Number of log files that can be made #define LOG_FILE_SUFFIX "csv" // Suffix of the log file char logFileName[13]; // Char string to store the log file name // Data to be logged: #define LOG_COLUMN_COUNT 8 char * log_col_names[LOG_COLUMN_COUNT] = { "longitude", "latitude", "altitude", "speed", "course", "date", "time", "satellites" }; // log_col_names is printed at the top of the file. ////////////////////// // Log Rate Control // ////////////////////// #define LOG_RATE 5000 // Log every 5 seconds unsigned long lastLog = 0; // Global var to keep of last time we logged ///////////////////////// // TinyGPS Definitions // ///////////////////////// TinyGPSPlus tinyGPS; // tinyGPSPlus object to be used throughout #define GPS_BAUD 9600 // GPS module's default baud rate //////////////////////////////////////////////// // Arduino GPS Shield Serial Port Definitions // //////////////////////////////////////////////// // If you're using an Arduino Uno, Mega, RedBoard, or any board that uses the // 0/1 UART for programming/Serial monitor-ing, use SoftwareSerial: #include <SoftwareSerial.h> #define ARDUINO_GPS_RX 3 // GPS TX, Arduino RX pin #define ARDUINO_GPS_TX 2 // GPS RX, Arduino TX pin SoftwareSerial ssGPS(ARDUINO_GPS_TX, ARDUINO_GPS_RX); // Create a SoftwareSerial SoftwareSerial SIM900(10, 11); // Set gpsPort to either ssGPS if using SoftwareSerial or Serial1 if using an // Arduino with a dedicated hardware serial port #define gpsPort ssGPS // Alternatively, use Serial1 on the Leonardo // Define the serial monitor port. On the Uno, Mega, and Leonardo this is 'Serial' // on other boards this may be 'SerialUSB' #define SerialMonitor Serial void setup() { SIM900.begin(9600); SerialMonitor.begin(9600); gpsPort.begin(GPS_BAUD); SerialMonitor.println("Setting up SD card."); // see if the card is present and can be initialized: if (!SD.begin(ARDUINO_USD_CS)) { SerialMonitor.println("Error initializing SD card."); } updateFileName(); // Each time we start, create a new file, increment the number printHeader(); // Print a header at the top of the new file } void loop() { if ((lastLog + LOG_RATE) <= millis()) { // If it's been LOG_RATE milliseconds since the last log: if (tinyGPS.location.isUpdated()) // If the GPS data is vaild { if (logGPSData()) // Log the GPS data { SerialMonitor.println("GPS logged."); // Print a debug message lastLog = millis(); // Update the lastLog variable } else // If we failed to log GPS { // Print an error, don't update lastLog SerialMonitor.println("Failed to log new GPS data."); } } else // If GPS data isn't valid { // Print a debug message. Maybe we don't have enough satellites yet. SerialMonitor.print("No GPS data. Sats: "); SerialMonitor.println(tinyGPS.satellites.value()); } } // If we're not logging, continue to "feed" the tinyGPS object: while (gpsPort.available()) tinyGPS.encode(gpsPort.read()); } byte logGPSData() { File logFile = SD.open(logFileName, FILE_WRITE); // Open the log file if (logFile) { // Print longitude, latitude, altitude (in feet), speed (in mph), course // in (degrees), date, time, and number of satellites. logFile.print(tinyGPS.location.lng(), 6); logFile.print(','); logFile.print(tinyGPS.location.lat(), 6); logFile.print(','); logFile.print(tinyGPS.altitude.feet(), 1); logFile.print(','); logFile.print(tinyGPS.speed.mph(), 1); logFile.print(','); logFile.print(tinyGPS.course.deg(), 1); logFile.print(','); logFile.print(tinyGPS.date.value()); logFile.print(','); logFile.print(tinyGPS.time.value()); logFile.print(','); logFile.print(tinyGPS.satellites.value()); logFile.println(); logFile.close();
GSMsms(); return 1; // Return success } return 0; // If we failed to open the file, return fail } // printHeader() - prints our eight column names to the top of our log file void printHeader() { File logFile = SD.open(logFileName, FILE_WRITE); // Open the log file if (logFile) // If the log file opened, print our column names to the file { int i = 0; for (; i < LOG_COLUMN_COUNT; i++) { logFile.print(log_col_names[i]); if (i < LOG_COLUMN_COUNT - 1) // If it's anything but the last column logFile.print(','); // print a comma else // If it's the last column logFile.println(); // print a new line } logFile.close(); // close the file } } // updateFileName() - Looks through the log files already present on a card, // and creates a new file with an incremented file index. void updateFileName() { int i = 0; for (; i < MAX_LOG_FILES; i++) { memset(logFileName, 0, strlen(logFileName)); // Clear logFileName string // Set logFileName to "gpslogXX.csv": sprintf(logFileName, "%s%d.%s", LOG_FILE_PREFIX, i, LOG_FILE_SUFFIX); if (!SD.exists(logFileName)) // If a file doesn't exist { break; // Break out of this loop. We found our index } else // Otherwise: { SerialMonitor.print(logFileName); SerialMonitor.println(" exists"); // Print a debug statement } } SerialMonitor.print("File name: "); SerialMonitor.println(logFileName); // Debug print the file name }
void sendsms() { delay(400); Serial.println("AT + CMGS = \"+55xxxxxxxxxxxx\""); delay(300);
Serial.print("http://maps.google.com/maps?q=loc:"); //SIM900.print("Latitude = "); Serial.print(tinyGPS.location.lat(), 6); //SIM900.print(" Longitude = ");
Serial.print(","); Serial.print(tinyGPS.location.lng(), 6); delay(200); Serial.println((char)26); // End AT command with a ^Z, ASCII code 26 delay(200); Serial.println();
if (millis() > 5000 && tinyGPS.charsProcessed() < 10) { Serial.println(F("No GPS detected: check wiring.")); while(true); } }
void comando(String comand) { conta++; avalia = ""; SIM900.print(comand); while(SIM900.available()<=0) Serial.print("preso passo "), Serial.println(conta), delay(200);
while(SIM900.available()>0) { char letra = SIM900.read(); if (isAlphaNumeric(letra)) avalia += letra; }
if (avalia=="OK") Serial.print("passo"), Serial.println(conta); else Serial.print("avalia: "), Serial.println(avalia); delay(200); }
void GSMsms() { comando("AT+CMGF=1\r\n"); comando("ATE0\r\n"); comando("AT+CNMI=1,2,0,0,0\r\n"); /* SIM900.print("AT+CMGF=1\r"); SIM900.print("ATE0\r"); SIM900.print("AT+CNMI=1,2,0,0,0\r"); */ delay(400);
SIM900.print("AT+CMGS=\r\n"); SIM900.write(0x22);//aspa dupla SIM900.print("+55xxxxxxxxx"); SIM900.write(0x22);//aspa dupla SIM900.println(); delay(400);
SIM900.print("http://maps.google.com/maps?q=loc:"); SIM900.print(tinyGPS.location.lat(), 6); SIM900.print(","); SIM900.print(tinyGPS.location.lng(), 6); SIM900.write(0x1A); SIM900.write(0x0D); SIM900.write(0x0A); Serial.println("Enviando mensagem..."); delay(1000); }
HARDWARE USADO :
SIM 900A
ARDUINO UNO
ARDUINO SHIELD…
Adicionado por Rafael Q. S. ao 22:41 em 4 outubro 2019
eracional) considerado ultrapassado (e isso já a mais de 30 anos). Assim seu uso em um Projeto Acadêmico, pode acabar sendo visto por alguns Professores, como algo inadequado. Apesar da sua justificativa (que vc me disse pelo chat) ser compreensível, não deixe de levar em consideração aspectos práticos como a extensa disponibilidade de AOs muito mais adequados a Projetos e custos envolvidos. Alguns aspectos tecnológicos podem também ser fundamentais, como variação de parâmetros com a temperatura, etc.
2) no estágio do Pré-Amplificador, "C7" garante que níveis DC não sejam amplificados, e também facilita o acoplamento do sinal de entrada (até certo ponto!). Ele também garante o mínimo de efeito do Offset de Tensão do AO na saída deste estágio.
Mas provavelmente seria melhor eliminar o ajuste do Ganho substituindo "POT_U1" por um Resistor fixo, e diminuir o Ganho neste estágio, e caso o Ganho não seja o que vc deseja, compense em um segundo estágio (e não no estágio de saída!). Isto seria muito facilitado se vc usar um CI mais "moderno", preferencialmente um que tem 4 AOs.
E se vc mantiver o ajuste de offset através do trimpot de 10k, vc precisará curto-circuitar "C7" durante esse ajuste, do contrário o ajuste não será possível, já que "C7" suprime o nível DC na saída.
3) observe que "C7" não pode ser do tipo polarizado, pois a tensão DC sobre ele pode ser tanto positiva como negativa. Já existem fartamente disponíveis Capacitores Cerâmicos nesta faixa de "C7", notadamente com dielétrico X5R (que são excelentes, e eu já usei muito em projetos recentes). Há também X7R, mas costumam ser mais caros pois são em menor disponibilidade para Capacitâncias dessa faixa. Claro, neste caso, usar dois Eletrolíticos de Alumínio em série (e em "contra-polaridade"), também resolve a questão da polaridade (mas há ressalvas nas frequências de áudio mais altas, pois Eletrolíticos de Alumínio se comportam como indutores a partir de alguns kHz).
4) o valor de 1M para "POT_U2" está totalmente inadequado para a entrada do LM386. Ocorre que a Impedância de Entrada do LM386 é de 50k, e "POT_U2" teria que ter um valor pelo menos 10 vezes menor, ou seja: algo em torno de 5k, senão o ajuste será extremamente difícil e até sem sentido. Este valor de 5k, não compromete o consumo de energia, uma vez que neste ponto do circuito, tanto o sinal de áudio como qualquer remanescente DC, ainda tem amplitudes muito baixas (no caso do sinal de áudio, o valor RMS será baixíssimo neste ponto).
5) tente manter o Ganho do LM386, no menor valor possível, que neste caso seria 20. Estágios de Saída de Potência devem ser concebidos para ganhos baixos (em alguns casos até mesmo ganho igual a 1), pois isso minimiza o efeito de ruídos da fonte de alimentação. O ganho atual de 200 que vc está usando, provavelmente vai trazer algumas surpresas ruins.
6) sobre o consumo de energia, sempre é possível otimizar. Mas circuitos totalmente analógicos tem um limite para isto, e este limite não costuma ser muito baixo, principalmente em amplificadores de áudio. Então não espere grande resultado alimentando seu Sistema com Pilhas ou Baterias, mesmo que "modernas".
Se seu problema for com o 60Hz presente na Fonte de Alimentação (mesmo um 60Hz de 1mV que mal seria visto em um Osciloscópio, pode ser terrível em um Amplificador de áudio), uma outra solução pode ser usada. Vc pode filtrar de forma exclusiva, a alimentação do Pré-Amplificador. Como o estágio Pré consome pouca energia, esta filtragem é totalmente viável. Há diversas formas de fazer isso, mais uma das mais eficientes é através de um Filtro Passa-Baixas usando um "Gyrator" (veja um artigo na Revista Elektor-Brasil 6 de 1986). Eu já usei isto e recomendo.
Agora respondendo sua pergunta sobre a Impedância do Estágio de Entrada: nesta topologia que vc está usando com o AO, a Impedância de Entrada já é a máxima possível. Veja: não são os 2M Ohms que vc deixou descrito no circuito. É muito maior que isso (certamente mais de 1Giga Ohm). Essa é uma característica da configuração "não-inversora" que vc está usando com o AO (e claro que "Zin" depende da frequência, mas para a faixa de áudio, isto é negligenciável).
Mas pode ser que seja vantajoso ter uma impedância mais baixa, por exemplo na casa das dezenas ou centenas de kilo-Ohms. Vai depender de quem é a sua fonte de sinal. Caso sua fonte de sinal tenha uma impedância de saída relativamente baixa, então vc não precisa ter um estágio Pré com uma Impedância de Entrada extremamente alta. Considere isto, pois quanto mais alta a Impedância em um Circuito, mais susceptível a ruídos será este Circuito.
Espero ter ajudado.
abrçs,
Elcids…
Adicionado por Elcids Chagas ao 2:24 em 12 agosto 2021
eferência para seu Sistema atual e suas futuras implementações. E depois de publicado este, irei fazer uma pequena melhoria em termos de desempenho na precisão do processo de medir o Fluxo (ou a RPM de algo em um Sistema), e publicarei aqui também.
Não deixe de ler todo o texto, pois há considerações importantes nele.
Lembrando que este tópico é praticamente uma continuação de outro do J. Leonardo, onde publiquei uma implementação inicial, e que está neste link: "Medição Vazão 1"
Mas antes, comentando sobre as fotos do seu Sistema, ficou bem legal, e tem até uma personalização identificando o equipamento ("Hidrômetro Digital"). Vi também que o módulo Bluetooth HC-05 já está conectado no Sistema, e sobre isto, comento no final do post.
Como de costume, quando possível implemento também uma simulação, o que permite que aqueles que não tem o Hardware em mãos, possam testar, fazer experimentações, e aprender com isso.
Para a simulação, aproveitei o Sistema que eu já tinha publicado antes naquele seu outro tópico. Apenas tive que acrescentar no Hardware, a parte dos dois Botões de Controle e dos dois LEDs de sinalização de alertas. Também fiz um pequeno ajuste no circuito que "emula" o Sensor de Fluxo, a fim de que ele tivesse uma faixa de ajuste da "Vazão" mais de acordo com a faixa que vc está usando. O arquivo para simulação no Proteus está anexado no final do post.
Então começando pela simulação, o circuito pode ser visto na figura a seguir:
(clique na figura para "zoom")
Na figura a seguir, pode-se ver o resultado após quase 14 segundos de simulação (este tempo é "virtual").
(clique na figura para "zoom")
No Display LCD é exibida a informação conforme selecionada via Botões de controle "Up" e "Down", e no Terminal do Arduino são "printados" dados a cada segundo (ou seja, a cada vez que é obtida uma nova amostragem da Vazão).
Nota-se que além da Vazão "instantânea", também é "printado" no Terminal do Arduino, a Vazão Média (sobre a qual falo mais adiante), a qual vai aumentando até praticamente se igualar ao valor instantâneo (como esperado).
Mas após isso, eu aumentei em "TP10" (o Trimpot para ajuste do Fluxo), para que a Vazão ficasse acima do Limite (que é 1 L/minuto).
O tempo necessário para detectar a Vazão Limite é de 5 minutos conforme o J. Leonardo especificou, ou seja, a Vazão tem que ficar acima do Limite por 5 minutos para que seja emitido um alerta. Porém, apenas na simulação eu diminui este tempo para 1 minuto, para não ter que esperar muito para ver o resultado.
E este resultado pode ser visto na figura a seguir, que mostra ligado o LED vermelho "Alerta Vazão":
(clique na figura para "zoom")
Nota-se também que pelo tempo decorrido, que novamente o valor da Vazão Média praticamente já igualou a Vazão instantânea.
Agora falando sobre o código, cujo link para download está no final do post.
Um ponto importante a salientar, é que o Sistema calcula continuamente a Vazão Média, e usa esse valor como referência para determinar se a Vazão Limite (no caso, 1 L/minuto) foi excedida (claro, após se manter assim por tempo determinado). Isso é necessário porque a Vazão "instantânea" terá variações, o que poderá impedir o Sistema de detectar o limite e emitir um alerta. Exemplo: a Vazão Limite é de 2 L/minuto e a Vazão instantânea está em 2,1 L/min a algum tempo, mas cai por 3 segundos para 1,9 L/min, e em seguida volta a subir indo para 2,3 L/min. Neste caso, quando a Vazão caiu momentaneamente para 1,9 L/min, isto interromperia a contagem de tempo para emissão de um alerta, o que seria um problema caso essas quedas ficassem ocorrendo e impedindo o alerta de ser emitido. Usando a Vazão Média, diminui-se a possibilidade desse problema, uma vez que variações momentâneas na Vazão, terão efeito menor no valor da Vazão Média.
No código, você pode determinar quantas amostras irão compor a Vazão Média, conforme mostro mais adiante.
Além de usar a Vazão Média para o alerta, o código também tem uma tolerância para o valor da Vazão Limite, sendo esta tolerância sempre "para baixo" (já que não teria sentido ser também "para cima"). Exemplo: se a Vazão Limite é de 2 L/min, e a tolerância é definida para 10%, então o Sistema considera como valor limite efetivo, os 2 L/min menos 10% de 2 L/min. Ou seja, 2 - 0.1 x 2 = 1,8 L/minuto. A tolerância pode ser facilmente alterada no código (como mostro adiante), e caso não se deseje utilizá-la basta então especificar uma tolerância de 0%.
A verificação para alerta de Vazão Limite, é temporizada, ou seja, é feita em intervalos de tempo. No código, este intervalo de tempo está especificado em segundos (como mostro logo adiante). Como resultado, esta temporização também ajuda a minimizar alertas errôneos, uma vez que pequenas variações podem até ser ignoradas pelo Sistema. Exemplo: a Vazão Média está próxima ao limite mas abaixo dele, e fica acima desse limite por 5 segundos, voltando a ficar abaixo em seguida, e como isso ocorre entre dois intervalos de verificação, a variação acaba não sendo detectada (mas seria, se fosse efetiva e ficasse mais tempo acima do limite).
Outros detalhes de definições no código, são descritos a seguir na ordem que eles aparecem no próprio código. Lembrando que logo no início do código, estão definidos os parâmetros mais significativos e que são normalmente os mais alterados em implementações diversas. A quantidade de parâmetros é um pouco extensa, e além das definições de parâmetros constantes, há também algumas variáveis/flags importantes para o funcionamento do Sistema. No texto a seguir, descrevo os tais parâmetros mais significativos e aponto algumas funções mais relevantes para o Sistema.
A figura a seguir, mostra a definição dos fatores para cálculo da Vazão "instantânea" e da conta de água.
(clique na figura para "zoom")
O "fator_Vazão" permite o cálculo da Vazão "instantânea" em mili-Litros por segundo. Assim no código, para se obter a Vazão em Litros por minuto, basta multiplicar a Vazão instantânea por 60 (já que 60 segundos= 1 minuto) e dividir por 1000 (já que 1000 mili-Litros = 1 Litro).
Na figura a seguir, são mostrados os parâmetros usados para determinar se o Sistema deve emitir um alerta de Vazão acima de um limite definido. A figura é auto-explicativa, uma vez que os comentários no código descrevem cada parâmetro e explicam como são usados.
(clique na figura para "zoom")
O Sistema emite também um alerta quando o consumo total (o fluxo total acumulado), ultrapassa um limite estabelecido. A figura a seguir, mostra a definição deste limite, em metros cúbicos:
(clique na figura para "zoom")
Observar que como o fluxo é sempre cumulativo, não é necessário tratamento especial (como calcular um valor médio) para se detectar um limiar e consequentemente emitir um alerta.
Além de mensagem no Display LCD, dois LEDs são usados para sinalizar o alerta de Vazão Limite e alerta de fluxo total acumulado. A figura a seguir mostra as definições para uso destes LEDs no Sistema:
(clique na figura para "zoom")
Sinalizar através de LED é uma forma eficiente de emitir um alerta (alertas auditivos geralmente são mais eficientes, mas nem sempre são os mais adequados devido ao "barulho" resultante). Mas é preciso considerar a cor usada para o alerta visual, neste caso a cor da luz que os LEDs emitem. Eu projetei Equipamentos Eletro-Médicos por 25 anos, e conheço bem as normas relacionadas a alertas naqueles equipamentos (normas compulsórias neste caso), onde alertas visuais devem se restringir a cores como "amarelo", "laranja", "vermelho", e tons semelhantes. Ou seja, não tem sentido sinalizar um alerta com uma cor como "verde" ou "azul" (ou mesmo "branco"). Aqui neste tópico não estamos tratando de equipamentos médicos, mas observem que o bom senso do uso das cores também se aplica de forma muito natural para sinalizarmos alertas.
Para selecionar a informação exibida no Display, são usados dois Botões chamados de "Up" e "Down". Acredito que apenas um Botão seria suficiente para esta função, mas o J. Leonardo optou por dois. Mas além disso, um Botão a mais permite mais opções de uso, e isso certamente será necessário se as funcionalidades do código forem expandidas por quem assim desejar (é bem provável que um terceiro e um quarto Botão sejam bem vindos). Os dois Botões são definidos conforme mostra a figura a seguir:
(clique na figura para "zoom")
Como o Sistema é originalmente para o Arduino UNO (ou seja, com Processador "AVR"), o código automaticamente ligará o Resistor de Pullup interno no pino dos Botões, caso o Nível Lógico de acionamento (com nome "logica_Botao_ON" na figura anterior) seja "LOW", assim dispensando um Pullup externo. Lembrando que o Pullup interno do AVR tem um valor com alta-tolerância, podendo ir de 20 kΩ a 50 kΩ (depende da tensão de alimentação, sendo que tensões mais altas neste caso implicam em impedâncias mais baixas, pois são usados MOSFETs para "construir" os Resistores de pullup). Caso o código seja usado em Sistemas com outros Processadores que permitam também "Pulldown" (como ESP32, STM32, Arduino Due, etc), então pode-se usar a mesma técnica para ligar automaticamente ou o "Pullup" ou o "PullDown" (ou mesmo nenhum deles, caso se especifique que um Resistor externo esteja sendo usado).
Para eliminar o "bouncing" (ou trepidação mecânica) resultante do acionamento de um Botão, e assim impedir acionamentos errôneos consecutivos, o Sistema implementa um "tempo de debouncing". Assim quando um Botão é acionado, o Sistema ignora qualquer outro acionamento no mesmo botão, pelo "tempo de debouncing", e isso faz com que a trepidação mecânica não tenha efeito. Como existem Botões de todo tipo no mercado e com maior ou menor trepidação mecânica, é preciso definir qual o tempo de "debouncing" a ser utilizado no Sistema, e isto pode ser visto na figura a seguir:
(clique na figura para "zoom")
Por razões óbvias, este tempo está especificado em unidades de mili-segundos. O tempo de 100 [ms] definido na figura anterior, é geralmente mais que suficiente mesmo para os "piores" Botões, mas pode-se diminuir ou aumentar o mesmo caso seja desejado. Este tempo não tem efeito na detecção imediata do Botão, ou seja, quando um Botão é acionado ele será imediatamente detectado. Claro, se o tempo for especificado como "0" (zero), então o "tempo de debouncing" não terá efeito (ou seja, as trepidações mecânicas no acionamento provocarão diversos acionamentos).
Como já dito, o Sistema emite dois alertas: um de Vazão Limite e um alerta de Fluxo acumulado (um "alerta de consumo" total). Para ambos, há LEDs específicos para emissão de alerta visual. O alerta de Vazão Limite também é exibido periodicamente no Display (conforme descrito mais adiante). Caso seja desejado emitir outras formas de alerta, pode-se testar as Flags específicas para cada um dos dois alertas. Estas Flags são variáveis do tipo "bool" (ou "boolean"), e assumem o valor "true" ou o valor "false". Quando um alerta é emitido, a Flag respectiva vai ao valor "true". As variáveis correspondentes a estas Flags, são definidas conforme mostrado na figura a seguir:
(clique na figura para "zoom")
Logo, estas Flags podem ser testadas a qualquer momento e em qualquer ponto do código, para se saber se o alerta correspondente foi emitido. Lembrando que o consumo acumulado só aumenta, e portanto quando fica além do limite definido para alerta, este alerta passa a ser constante, ou seja, o LED de alerta fica permanentemente ligado e a Flag de alerta passa a ficar em "true" (e não volta mais para "false").
Também como dito antes, o Sistema calcula continuamente a Vazão Média em Litros por minuto, e para isso ele mantém um registro das últimas "N" amostras da Vazão instantânea. Esta quantidade "N" é definida conforme mostrado na figura a seguir:
(clique na figura para "zoom")
A Vazão Média será então o resultado do somatório das últimas "N" amostras, dividido pelo valor "N". No código este total de registros está definido como sendo 10 (dez), mas pode ser alterado conforme desejado (lembrando que quanto maior a quantidade de registros, mais memória RAM é usada para manter estes registros, e mais tempo o Sistema gasta para fazer os cálculos da Vazão Média).
Nota: a página do post não comporta o restante do texto, então estou continuando logo a seguir:
…
Adicionado por Elcids Chagas ao 1:09 em 20 novembro 2020
amente segue resposta obtida na software serial.
Starting ProcessGprsMsg();AT+CMGF=1 ProcessGprsMsg();ProcessGprsMsg(); OK ProcessGprsMsg();ProcessGprsMsg(); +CMTI: "SM",6
Si alguem poder me da uma força agradeço..
segue esbolso usado.
ch = strstr((char *)comm_buf, compare_string); if (ch != NULL) { ret_val = 1; } else { /*#ifdef DEBUG_PRINT DebugPrint("\r\nDEBUG: expected string was NOT received\r\n", 0); #endif */ } }
return (ret_val); }
byte WaitResp(uint16_t start_comm_tmout, uint16_t max_interchar_tmout) { byte status;//programmer gudjon@undri.com
//todo:sorry about the messy coding (not enough time to fix)
#include <SoftwareSerial.h>
//FOR MEGA decomment line below. On the EFCom shield DIS-connect the jumpers and put jumperwires from SHIELD RX to MEGA 51 and from SHIELD TX to MEGA 50SoftwareSerial mySerial(50, 51);
//FOR UNO decomment line below. On the EFCom shield connect the jumers, TX to D2 and RX to D3.//SoftwareSerial mySerial(2, 3);
/*EFcom/GPRS Shield Light meaning.------------------------------------------------------------------------| LED STATUS DESCRIPTION || --- ----------------- ---------------------------------------------|| PWR ON Power on the EFcom || PWR OFF Power off the EFcom || STA ON Power on the SIM900 OFF Power Off the SIM900 || NET OFF SIM900 is not running || NET 64ms ON/800ms OFF SIM900 not register the Network || NET 64ms ON/3000ms OFF SIM900 registered to the network || NET 64ms ON/300ms OFF GPRS communication is established |--- -------------------------------------------------------------------*/
///////////////////////////////////////////////////////////////////////////////////////
//SELECT HERE WICH PINS YOU WANT TO CONTROL ON THE ARDUINO (THEY must be in sequence)#define OPIN_FIRST 30#define OPIN_LAST 33//when program starts turn all pins on or off. allowed values are either HIGH or LOW#define OPIN_STARTSTATE LOW//The controlling phonenumber;#define PHONENUMBER "meu numero"
///////////////////////////////////////////////////////////////////////////////////////
String msg = String("");int SmsContentFlag = 0;
#define GSM_POWER 6 /*EFCom power pin*/#define GSM_RESET 5 /*EFCom reset pin**/
// S T A R T S T A R T Borrowed from GSMSHIELD Library S T A R T S T A R T //// some constants for the IsRxFinished() method// length for the internal communication buffer#define COMM_BUF_LEN 300#define RX_NOT_STARTED 0#define RX_ALREADY_STARTED 1
// variables connected with communication bufferbyte *p_comm_buf; // pointer to the communication bufferbyte comm_buf_len; // num. of characters in the bufferbyte rx_state; // internal state of rx state machine uint16_t start_reception_tmout; // max tmout for starting receptionuint16_t interchar_tmout; // previous time in msec.unsigned long prev_time; // previous time in msec.byte comm_buf[COMM_BUF_LEN+1]; // communication buffer +1 for 0x00 termination enum rx_state_enum {RX_NOT_FINISHED = 0, // not finished yetRX_FINISHED, // finished, some character was receivedRX_FINISHED_STR_RECV, // finished and expected string receivedRX_FINISHED_STR_NOT_RECV, // finished, but expected string not receivedRX_TMOUT_ERR, // finished, no character received // initial communication tmout occurredRX_LAST_ITEM};void RxInit(uint16_t start_comm_tmout, uint16_t max_interchar_tmout){rx_state = RX_NOT_STARTED;start_reception_tmout = start_comm_tmout;interchar_tmout = max_interchar_tmout;prev_time = millis();comm_buf[0] = 0x00; // end of stringp_comm_buf = &comm_buf[0];comm_buf_len = 0;mySerial.flush(); // erase rx circular buffer}
byte IsRxFinished(void){byte num_of_bytes;byte ret_val = RX_NOT_FINISHED; // default not finished
if (rx_state == RX_NOT_STARTED) {// Reception is not started yet - check tmoutif (!mySerial.available()) {// still no character received => check timeout
if ((unsigned long)(millis() - prev_time) >= start_reception_tmout) {// timeout elapsed => GSM module didn't start with response// so communication is takes as finishedcomm_buf[comm_buf_len] = 0x00;ret_val = RX_TMOUT_ERR;}}else {// at least one character received => so init inter-character // counting process again and go to the next stateprev_time = millis(); // init tmout for inter-character spacerx_state = RX_ALREADY_STARTED;}}
if (rx_state == RX_ALREADY_STARTED) {// Reception already started// check new received bytes// only in case we have place in the buffernum_of_bytes = mySerial.available();// if there are some received bytes postpone the timeoutif (num_of_bytes) prev_time = millis();// read all received bytes while (num_of_bytes) {num_of_bytes--;if (comm_buf_len < COMM_BUF_LEN) {// we have still place in the GSM internal comm. buffer =>// move available bytes from circular buffer // to the rx buffer*p_comm_buf = mySerial.read();
p_comm_buf++;comm_buf_len++;comm_buf[comm_buf_len] = 0x00; // and finish currently received characters// so after each character we have// valid string finished by the 0x00}else {mySerial.read();}}if ((unsigned long)(millis() - prev_time) >= interchar_tmout) {comm_buf[comm_buf_len] = 0x00; // for sure finish string again// but it is not necessaryret_val = RX_FINISHED;}}return (ret_val);}
/**********************************************************Method checks received bytes
compare_string - pointer to the string which should be find
return: 0 - string was NOT received1 - string was received**********************************************************/byte IsStringReceived(char const *compare_string){char *ch;byte ret_val = 0;
if(comm_buf_len) {#ifdef DEBUG_ONSerial.println("ATT: ");Serial.print(compare_string);Serial.print("RIC: ");Serial.println((char *)comm_buf);#endif
RxInit(start_comm_tmout, max_interchar_tmout); // wait until response is not finished do { status = IsRxFinished(); } while (status == RX_NOT_FINISHED); return (status); }
///////////////þarf eþtta kannski ekki sjá fyrir ofan byte WaitResp(uint16_t start_comm_tmout, uint16_t max_interchar_tmout, char const *expected_resp_string) { byte status; byte ret_val;
RxInit(start_comm_tmout, max_interchar_tmout); // wait until response is not finished do { status = IsRxFinished(); } while (status == RX_NOT_FINISHED);
if (status == RX_FINISHED) { // something was received but what was received? // --------------------------------------------- if(IsStringReceived(expected_resp_string)) { // expected string was received // ---------------------------- ret_val = RX_FINISHED_STR_RECV; } else { ret_val = RX_FINISHED_STR_NOT_RECV; } } else { // nothing was received // -------------------- ret_val = RX_TMOUT_ERR; } return (ret_val); } ///////////////þarf eþtta kannski ekki endir
/********************************************************** Method sends AT command and waits for response
return: -1, // no response received 0, // response_string is different from the response 1, // response_string was included in the response **********************************************************/ char SendATCmdWaitResp(char const *AT_cmd_string, uint16_t start_comm_tmout, uint16_t max_interchar_tmout, char const *response_string, byte no_of_attempts) { byte status; char ret_val = -1; byte i;
for (i = 0; i < no_of_attempts; i++) { // delay 500 msec. before sending next repeated AT command // so if we have no_of_attempts=1 tmout will not occurred if (i > 0) delay(500);
mySerial.println(AT_cmd_string); status = WaitResp(start_comm_tmout, max_interchar_tmout); if (status == RX_FINISHED) { // something was received but what was received? // --------------------------------------------- if(IsStringReceived(response_string)) { ret_val = 1; break; // response is OK => finish } else ret_val = 0; } else { // nothing was received // -------------------- ret_val = -1; } } return (ret_val);
}//char SendATCmdWaitRes
/********************************************************** Method sends SMS
number_str: pointer to the phone number string message_str: pointer to the SMS text string
return: ERROR ret. val: --------------- -1 - comm. line to the GSM module is not free -2 - GSM module didn't answer in timeout -3 - GSM module has answered "ERROR" string
OK ret val: ----------- 0 - SMS was not sent 1 - SMS was sent
an example of usage: GSM gsm; gsm.SendSMS("00XXXYYYYYYYYY", "SMS text"); **********************************************************/ char SendSMS(char *number_str, char *message_str) { char end[2]; end[0]=0x1a; end[1]='\0';/* Ctrl+Z */ mySerial.print("\r"); delay(1000); //Wait for a second while the modem sends an "OK" mySerial.print("AT+CMGF=1\r"); //Because we want to send the SMS in text mode delay(1000); //mySerial.print("AT+CSCA=\"+919032055002\"\r"); //Setting for the SMS Message center number, //delay(1000); //uncomment only if required and replace with //the message center number obtained from //your GSM service provider. //Note that when specifying a tring of characters // " is entered as \" mySerial.print("AT+CMGS=\"");mySerial.print(number_str); mySerial.print("\"\r"); //Start accepting the text for the message //to be sent to the number specified. //Replace this number with the target mobile number. delay(1000); mySerial.print(message_str); mySerial.print("\r"); //The text for the message delay(1000); mySerial.print(end); }
//// E N D E N D Borrowed from GSMSHIELD Library E N D E N D // //// //// S E T U P S E T U P S E T U P S E T U P S E T U P S E T U P S E T U P S E T U P S E T U P S E T U P S E T U P //// S E T U P S E T U P S E T U P S E T U P S E T U P S E T U P S E T U P S E T U P S E T U P S E T U P S E T U P //// S E T U P S E T U P S E T U P S E T U P S E T U P S E T U P S E T U P S E T U P S E T U P S E T U P S E T U P void setup() { mySerial.begin(9600); Serial.begin(9600); if (-1 == SendATCmdWaitResp("AT", 500, 100, "OK", 5)) { digitalWrite(GSM_POWER, HIGH);delay(3000); digitalWrite(GSM_POWER, LOW);delay(2000); } for(int i=OPIN_FIRST;i<OPIN_LAST+1;i++) { pinMode(i, OUTPUT); digitalWrite(i,OPIN_STARTSTATE); } Serial.println( "Starting" ); mySerial.println( "AT+CMGF=1" ); delay(200); } boolean bFoundMSGandNumber=false; void loop() { char SerialInByte; if(mySerial.available()) { SerialInByte = (unsigned char)mySerial.read(); delay(5);
if( SerialInByte == 13 ){ ProcessGprsMsg(); } if( SerialInByte == 10 ){ } else { msg += String(SerialInByte); } }
}
void ProcessSms( String sms ){ Serial.print("ProcessSms:");Serial.println(sms); String finna = String("xxxxx"); for(int i=OPIN_FIRST;i<OPIN_LAST+1;i++) { finna=String("Off");finna+=i; if( sms.indexOf(finna) >= 0 || sms.indexOf("Offall") >= 0 ){digitalWrite(i, LOW); Serial.println(finna);} } for(int i=OPIN_FIRST;i<OPIN_LAST+1;i++) { finna=String("On");finna+=i; if( sms.indexOf(finna) >= 0 || sms.indexOf("Onall") >= 0){digitalWrite(i, HIGH); Serial.println(finna);} } if( sms.indexOf("List") >= 0 ) { finna="stada"; for(int i=OPIN_FIRST;i<OPIN_LAST+1;i++) { finna+=" ";finna+=i;finna+="=";finna+=digitalRead(i); } int iSize=finna.length()+1; char charBuf[iSize]; finna.toCharArray(charBuf, iSize); SendSMS(PHONENUMBER, charBuf); } mySerial.println( "AT+CMGDA=\"DEL ALL\"" ); delay(200); } // EN: Request Text Mode for SMS messaging void GprsTextModeSMS(){ mySerial.println( "AT+CMGF=1" ); }
void GprsReadSmsStore( String SmsStorePos ){ mySerial.print( "AT+CMGR=" ); mySerial.println( SmsStorePos ); }
// EN: Clear the GPRS shield message buffer void ClearGprsMsg(){ msg = ""; }
// EN: interpret the GPRS shield message and act appropiately void ProcessGprsMsg() { Serial.print( "ProcessGprsMsg();");Serial.println(msg); if( msg.indexOf( "Call Ready" ) >= 0 ){ Serial.println( "*** GPRS Shield registered on Mobile Network ***" ); GprsTextModeSMS(); } //todo: búa til define string úr PHONENUMBER char findMe[strlen(PHONENUMBER)+2];strcpy(findMe,PHONENUMBER);strcat(findMe,"\""); if( (msg.indexOf( "+CMT" ) >= 0) && (msg.indexOf( findMe )>0) ){ Serial.println( "*** SMS Received ***" ); bFoundMSGandNumber=true; } else { if(bFoundMSGandNumber==true) { ProcessSms( msg ); } bFoundMSGandNumber=false; } ClearGprsMsg(); SmsContentFlag = 0; }
int getValidPin(char *pNum) { int iNum=strlen(pNum); if (iNum<1 || iNum>2) return false;//pin must be from 0..99 iNum = atoi (pNum); if ((iNum < OPIN_FIRST) || (iNum > OPIN_LAST)) return false;//num must be equal or between OPIN_FIRST and OPIN_FIRST
return iNum; }…
Adicionado por Paulo souza ao 21:39 em 8 setembro 2014
ve(unsigned char slave, int *regs,unsigned int regs_size);enum {COMM_BPS = 9600, /* baud rate */MB_SLAVE = 1, /* endereço do escravo modbus *//* cada escravo modbus deve ter um *//* endereço único na rede modbus */PARITY = 'n', /* paridade */TXEN = 6 /*Definir o pino usado para colocar o driver RS485 em modo de transmissão, utilizado somente em redes RS485 quando colocar em 0 ou 1 para redes RS232 */};/* registros do escravo (holding registers)** Aqui ficam ordenados todos os registros de leitura e escrita* da comunicação entre o mestre e o escravo (SCADA e arduino)**/enum {MB_PINO_5, /* Controle do Led no pino 3 (desliga=0 liga=1) offset 0 (p/ data point no scadabr)*/MB_PINO_4, /* Leitura da chave no pino 4 (desliga=0 liga=1) offset 1 (p/ data point no scadabr)*/MB_A0, /* Leitura da entrada analógica 0 (0 a 1023) offset 2 (p/ data point no scadabr)*/MB_REGS /* número total de registros do escravo */};int regs[MB_REGS];int ledPin5 = 5;int ledPin13 = 13;int buttonPin4 = 4;int buttonState = 0; // variável para ler e estado do botãounsigned long wdog = 0; /* watchdog */unsigned long tprev = 0; /* tempo anterior do último comando*/unsigned long tanalogprev = 0; /* tempo anterior da leitura dos pinos analógicos*/void setup(){/* configura cominicação modbus* 9600 bps, 8N1, RS485 network */ configure_mb_slave(COMM_BPS, PARITY, TXEN); pinMode(3,OUTPUT); pinMode(4,OUTPUT); pinMode(5,INPUT); pinMode(6,INPUT);}void loop(){/* verifica se há solicitações do mestre */if(update_mb_slave(MB_SLAVE, regs, MB_REGS))wdog = millis();if ((millis() - tanalogprev) > 1000) { /* atualiza as entradas analogica a cada 1 segundo */regs[MB_A0] = analogRead(0); /* ler entrada analógica 0 e salva valor no registro modbus*/tanalogprev = millis();}buttonState = digitalRead(buttonPin4); // ler estado da chave no pino 4regs[MB_PINO_4] = buttonState; // salva valor no registro modbusif (buttonState == HIGH) { // caso a chave esteja pressionadadigitalWrite(ledPin13, HIGH); // liga o Led do pino 13}else { // caso a chave não esteja pressionadadigitalWrite(ledPin13, LOW); // desliga o Led do pino 13}/* os valores do registro MB_PINO_5 é definido pelo mestre modbus (SCADA) */switch(regs[MB_PINO_5]) {case 1:digitalWrite(ledPin5, HIGH);break;default: /* apagado */digitalWrite(ledPin5, LOW);}}/***************************************************************************** INICIO DAS FUNÇÕES ESCRAVO Modbus RTU****************************************************************************//* variaveis globais */unsigned int Txenpin = TXEN; /*Definir o pino usado para colocar o driver RS485 em modo de transmissão, utilizado somente em redes RS485 quando colocar em 0 ou 1 para redes RS232 *//* Lista de códigos de função modbus suportados. Se você implementar um novo, colocar o seu código de função aqui! */enum{FC_READ_REGS = 0x03, /*Ler um bloco contiguo de registros*/FC_WRITE_REG = 0x06, /*Escrever em um único registro*/FC_WRITE_REGS = 0x10 /*Escrever em um bloco contíguo de registos*/};/* Funções suportadas. Se você implementar um novo, colocar seu código em função nessa matriz! */const unsigned char fsupported[] = {FC_READ_REGS, FC_WRITE_REG, FC_WRITE_REGS };/* constantes */enum {MAX_READ_REGS = 0x7D,MAX_WRITE_REGS = 0x7B,MAX_MESSAGE_LENGTH = 256};enum {RESPONSE_SIZE = 6,EXCEPTION_SIZE = 3,CHECKSUM_SIZE = 2};/* código de exceções */enum {NO_REPLY = -1,EXC_FUNC_CODE = 1,EXC_ADDR_RANGE = 2,EXC_REGS_QUANT = 3,EXC_EXECUTE = 4};/* posições dentro da matriz de consulta / resposta */enum {SLAVE = 0,FUNC,START_H,START_L,REGS_H,REGS_L,BYTE_CNT};/*CRCINPUTS:buf -> Matriz contendo a mensagem a ser enviada para o controlador mestre.start -> Início do loop no crc do contador, normalmente 0.cnt -> Quantidade de bytes na mensagem a ser enviada para o controlador mestreOUTPUTS:temp -> Retorna byte crc para a mensagem.COMMENTÁRIOS:Esta rotina calcula o byte crc alto e baixo de uma mensagem.Note que este CRC é usado somente para Modbus, não em Modbus PLUS ou TCP.****************************************************************************/unsigned int crc(unsigned char *buf, unsigned char start,unsigned char cnt){unsigned char i, j;unsigned temp, temp2, flag;temp = 0xFFFF;for (i = start; i < cnt; i++) {temp = temp ^ buf[i];for (j = 1; j <= 8; j++) {flag = temp & 0x0001;temp = temp >> 1;if (flag)temp = temp ^ 0xA001;}}/* Inverter a ordem dos bytes. */temp2 = temp >> 8;temp = (temp << 8) | temp2;temp &= 0xFFFF;return (temp);}/************************************************************************* As seguintes funções constroem o frame de* um pacote de consulta modbus.************************************************************************//** Início do pacote de uma resposta read_holding_register*/void build_read_packet(unsigned char slave, unsigned char function,unsigned char count, unsigned char *packet){packet[SLAVE] = slave;packet[FUNC] = function;packet[2] = count * 2;}/** Início do pacote de uma resposta preset_multiple_register*/void build_write_packet(unsigned char slave, unsigned char function,unsigned int start_addr,unsigned char count,unsigned char *packet){packet[SLAVE] = slave;packet[FUNC] = function;packet[START_H] = start_addr >> 8;packet[START_L] = start_addr & 0x00ff;packet[REGS_H] = 0x00;packet[REGS_L] = count;}/** Início do pacote de uma resposta write_single_register*/void build_write_single_packet(unsigned char slave, unsigned char function,unsigned int write_addr, unsigned int reg_val, unsigned char* packet){packet[SLAVE] = slave;packet[FUNC] = function;packet[START_H] = write_addr >> 8;packet[START_L] = write_addr & 0x00ff;packet[REGS_H] = reg_val >> 8;packet[REGS_L] = reg_val & 0x00ff;}/** Início do pacote de uma resposta excepção*/void build_error_packet(unsigned char slave, unsigned char function,unsigned char exception, unsigned char *packet){packet[SLAVE] = slave;packet[FUNC] = function + 0x80;packet[2] = exception;}/*************************************************************************** modbus_query( packet, length)** Função para adicionar uma soma de verificação para o fim de um pacote.* Por favor, note que a matriz pacote deve ser de pelo menos 2 campos mais do que* String_length.**************************************************************************/void modbus_reply(unsigned char *packet, unsigned char string_length){int temp_crc;temp_crc = crc(packet, 0, string_length);packet[string_length] = temp_crc >> 8;string_length++;packet[string_length] = temp_crc & 0x00FF;}/************************************************************************* send_reply( query_string, query_length )** Função para enviar uma resposta a um mestre Modbus.* Retorna: o número total de caracteres enviados************************************************************************/int send_reply(unsigned char *query, unsigned char string_length){unsigned char i;if (Txenpin > 1) { // coloca o MAX485 no modo de transmissãoUCSR0A=UCSR0A |(1 << TXC0);digitalWrite( Txenpin, HIGH);delayMicroseconds(3640); // aguarda silencio de 3.5 caracteres em 9600bps}modbus_reply(query, string_length);string_length += 2;for (i = 0; i < string_length; i++) {Serial.write(byte(query[i]));}if (Txenpin > 1) {// coloca o MAX485 no modo de recepçãowhile (!(UCSR0A & (1 << TXC0)));digitalWrite( Txenpin, LOW);}return i; /* isso não significa que a gravação foi bem sucedida */}/************************************************************************* receive_request( array_for_data )** Função para monitorar um pedido do mestre modbus.** Retorna: Número total de caracteres recebidos se OK* 0 se não houver nenhum pedido* Um código de erro negativo em caso de falha***********************************************************************/int receive_request(unsigned char *received_string){int bytes_received = 0;/* FIXME: não Serial.available esperar 1.5T ou 3.5T antes de sair do loop? */while (Serial.available()) {received_string[bytes_received] = Serial.read();bytes_received++;if (bytes_received >= MAX_MESSAGE_LENGTH)return NO_REPLY; /* erro de porta */}return (bytes_received);}/*********************************************************************** modbus_request(slave_id, request_data_array)** Função que é retornada quando o pedido está correto* e a soma de verificação está correto.* Retorna: string_length se OK* 0 se não* Menos de 0 para erros de exceção** Nota: Todas as funções usadas para enviar ou receber dados via* Modbus devolver esses valores de retorno.***********************************************************************/int modbus_request(unsigned char slave, unsigned char *data){int response_length;unsigned int crc_calc = 0;unsigned int crc_received = 0;unsigned char recv_crc_hi;unsigned char recv_crc_lo;response_length = receive_request(data);if (response_length > 0) {crc_calc = crc(data, 0, response_length - 2);recv_crc_hi = (unsigned) data[response_length - 2];recv_crc_lo = (unsigned) data[response_length - 1];crc_received = data[response_length - 2];crc_received = (unsigned) crc_received << 8;crc_received =crc_received | (unsigned) data[response_length - 1];/*********** verificar CRC da resposta ************/if (crc_calc != crc_received) {return NO_REPLY;}/* verificar a ID do escravo */if (slave != data[SLAVE]) {return NO_REPLY;}}return (response_length);}/*********************************************************************** validate_request(request_data_array, request_length, available_regs)** Função para verificar se o pedido pode ser processado pelo escravo.** Retorna: 0 se OK* Um código de exceção negativa em caso de erro***********************************************************************/int validate_request(unsigned char *data, unsigned char length,unsigned int regs_size){int i, fcnt = 0;unsigned int regs_num = 0;unsigned int start_addr = 0;unsigned char max_regs_num;/* verificar o código de função */for (i = 0; i < sizeof(fsupported); i++) {if (fsupported[i] == data[FUNC]) {fcnt = 1;break;}}if (0 == fcnt)return EXC_FUNC_CODE;if (FC_WRITE_REG == data[FUNC]) {/* Para a função de escrever um reg único, este é o registro alvo.*/regs_num = ((int) data[START_H] << 8) + (int) data[START_L];if (regs_num >= regs_size)return EXC_ADDR_RANGE;return 0;}/* Para as funções de leitura / escrita de registros, este é o intervalo. */regs_num = ((int) data[REGS_H] << 8) + (int) data[REGS_L];/* verifica a quantidade de registros */if (FC_READ_REGS == data[FUNC])max_regs_num = MAX_READ_REGS;else if (FC_WRITE_REGS == data[FUNC])max_regs_num = MAX_WRITE_REGS;if ((regs_num < 1) || (regs_num > max_regs_num))return EXC_REGS_QUANT;/* verificará a quantidade de registros, endereço inicial é 0 */start_addr = ((int) data[START_H] << 8) + (int) data[START_L]; if ((start_addr + regs_num) > regs_size) return EXC_ADDR_RANGE; return 0; /* OK, no exception */}/************************************************************************** write_regs(first_register, data_array, registers_array)** escreve nos registradores do escravo os dados em consulta,* A partir de start_addr.** Retorna: o número de registros escritos************************************************************************/int write_regs(unsigned int start_addr, unsigned char *query, int *regs) { int temp; unsigned int i; for (i = 0; i < query[REGS_L]; i++) { /* shift reg hi_byte to temp */ temp = (int) query[(BYTE_CNT + 1) + i * 2] << 8; /* OR with lo_byte */ temp = temp | (int) query[(BYTE_CNT + 2) + i * 2]; regs[start_addr + i] = temp; } return i;}/************************************************************************** preset_multiple_registers(slave_id, first_register, number_of_registers,* data_array, registers_array)** Escreva os dados na matriz dos registos do escravo.**************************************************************************/int preset_multiple_registers(unsigned char slave,unsigned int start_addr,unsigned char count,unsigned char *query,int *regs){unsigned char function = FC_WRITE_REGS; /* Escrever em múltiplos registros */int status = 0;unsigned char packet[RESPONSE_SIZE + CHECKSUM_SIZE];build_write_packet(slave, function, start_addr, count, packet);if (write_regs(start_addr, query, regs)) {status = send_reply(packet, RESPONSE_SIZE);}return (status);}/************************************************************************** write_single_register(slave_id, write_addr, data_array, registers_array)** Escrever um único valor inteiro em um único registo do escravo.**************************************************************************/int write_single_register(unsigned char slave,unsigned int write_addr, unsigned char *query, int *regs){unsigned char function = FC_WRITE_REG; /* Função: Write Single Register */int status = 0;unsigned int reg_val;unsigned char packet[RESPONSE_SIZE + CHECKSUM_SIZE];reg_val = query[REGS_H] << 8 | query[REGS_L];build_write_single_packet(slave, function, write_addr, reg_val, packet);regs[write_addr] = (int) reg_val;/*written.start_addr=write_addr;written.num_regs=1;*/status = send_reply(packet, RESPONSE_SIZE);return (status);}/************************************************************************** read_holding_registers(slave_id, first_register, number_of_registers,* registers_array)** lê os registros do escravo e envia para o mestre Modbus**************************************************************************/int read_holding_registers(unsigned char slave, unsigned int start_addr,unsigned char reg_count, int *regs){unsigned char function = 0x03; /* Função 03: Read Holding Registers */int packet_size = 3;int status;unsigned int i;unsigned char packet[MAX_MESSAGE_LENGTH];build_read_packet(slave, function, reg_count, packet);for (i = start_addr; i < (start_addr + (unsigned int) reg_count);i++) {packet[packet_size] = regs[i] >> 8;packet_size++;packet[packet_size] = regs[i] & 0x00FF;packet_size++;}status = send_reply(packet, packet_size);return (status);}void configure_mb_slave(long baud, char parity, char txenpin){Serial.begin(baud);switch (parity) {case 'e': // 8E1UCSR0C |= ((1<<UPM01) | (1<<UCSZ01) | (1<<UCSZ00));// UCSR0C &= ~((1<<UPM00) | (1<<UCSZ02) | (1<<USBS0));break;case 'o': // 8O1UCSR0C |= ((1<<UPM01) | (1<<UPM00) | (1<<UCSZ01) | (1<<UCSZ00));// UCSR0C &= ~((1<<UCSZ02) | (1<<USBS0));break;case 'n': // 8N1UCSR0C |= ((1<<UCSZ01) | (1<<UCSZ00));// UCSR0C &= ~((1<<UPM01) | (1<<UPM00) | (1<<UCSZ02) | (1<<USBS0));break;default:break;}if (txenpin > 1) { // pino 0 & pino 1 são reservados para RX/TXTxenpin = txenpin; /* definir variável global */pinMode(Txenpin, OUTPUT);digitalWrite(Txenpin, LOW);}return;}/** update_mb_slave(slave_id, holding_regs_array, number_of_regs)** verifica se há qualquer pedido válido do mestre modbus. Se houver,* executa a ação solicitada*/unsigned long Nowdt = 0;unsigned int lastBytesReceived;const unsigned long T35 = 5;int update_mb_slave(unsigned char slave, int *regs,unsigned int regs_size){unsigned char query[MAX_MESSAGE_LENGTH];unsigned char errpacket[EXCEPTION_SIZE + CHECKSUM_SIZE];unsigned int start_addr;int exception;int length = Serial.available();unsigned long now = millis();if (length == 0) {lastBytesReceived = 0;return 0;}if (lastBytesReceived != length) {lastBytesReceived = length;Nowdt = now + T35;return 0;}if (now < Nowdt)return 0;lastBytesReceived = 0;length = modbus_request(slave, query);if (length < 1)return length;exception = validate_request(query, length, regs_size);if (exception) {build_error_packet(slave, query[FUNC], exception,errpacket);send_reply(errpacket, EXCEPTION_SIZE);return (exception);}start_addr = ((int) query[START_H] << 8) +(int) query[START_L];switch (query[FUNC]) {case FC_READ_REGS:return read_holding_registers(slave,start_addr,query[REGS_L],regs);break;case FC_WRITE_REGS:return preset_multiple_registers(slave,start_addr,query[REGS_L],query,regs);break;case FC_WRITE_REG:write_single_register(slave,start_addr,query,regs);break;}}…
DDLE NOZZLE_CLEAN_START_POINT
// Moves the nozzle to the initial position #define NOZZLE_CLEAN_GOBACK #endif
/** * Print Job Timer * * Automatically start and stop the print job timer on M104/M109/M190. * * M104 (hotend, no wait) - high temp = none, low temp = stop timer * M109 (hotend, wait) - high temp = start timer, low temp = stop timer * M190 (bed, wait) - high temp = start timer, low temp = none * * The timer can also be controlled with the following commands: * * M75 - Start the print job timer * M76 - Pause the print job timer * M77 - Stop the print job timer */ #define PRINTJOB_TIMER_AUTOSTART
/** * Print Counter * * Track statistical data such as: * * - Total print jobs * - Total successful print jobs * - Total failed print jobs * - Total time printing * * View the current statistics with M78. */ #define PRINTCOUNTER // habilita possibilidade de ver as estatisticas de impressao
//============================================================================= //============================= LCD and SD support ============================ //=============================================================================
// @section lcd
/** * LCD LANGUAGE * * Select the language to display on the LCD. These languages are available: * * en, an, bg, ca, cn, cz, cz_utf8, de, el, el-gr, es, es_utf8, * eu, fi, fr, fr_utf8, gl, hr, it, kana, kana_utf8, nl, pl, pt, * pt_utf8, pt-br, pt-br_utf8, ru, sk_utf8, tr, uk, zh_CN, zh_TW, test * * :{ 'en':'English', 'an':'Aragonese', 'bg':'Bulgarian', 'ca':'Catalan', 'cn':'Chinese', 'cz':'Czech', 'cz_utf8':'Czech (UTF8)', 'de':'German', 'el':'Greek', 'el-gr':'Greek (Greece)', 'es':'Spanish', 'es_utf8':'Spanish (UTF8)', 'eu':'Basque-Euskera', 'fi':'Finnish', 'fr':'French', 'fr_utf8':'French (UTF8)', 'gl':'Galician', 'hr':'Croatian', 'it':'Italian', 'kana':'Japanese', 'kana_utf8':'Japanese (UTF8)', 'nl':'Dutch', 'pl':'Polish', 'pt':'Portuguese', 'pt-br':'Portuguese (Brazilian)', 'pt-br_utf8':'Portuguese (Brazilian UTF8)', 'pt_utf8':'Portuguese (UTF8)', 'ru':'Russian', 'sk_utf8':'Slovak (UTF8)', 'tr':'Turkish', 'uk':'Ukrainian', 'zh_CN':'Chinese (Simplified)', 'zh_TW':'Chinese (Taiwan)', 'test':'TEST' } */ #define LCD_LANGUAGE pt-br
/** * LCD Character Set * * Note: This option is NOT applicable to Graphical Displays. * * All character-based LCDs provide ASCII plus one of these * language extensions: * * - JAPANESE ... the most common * - WESTERN ... with more accented characters * - CYRILLIC ... for the Russian language * * To determine the language extension installed on your controller: * * - Compile and upload with LCD_LANGUAGE set to 'test' * - Click the controller to view the LCD menu * - The LCD will display Japanese, Western, or Cyrillic text * * See http://marlinfw.org/docs/development/lcd_language.html * * :['JAPANESE', 'WESTERN', 'CYRILLIC'] */ #define DISPLAY_CHARSET_HD44780 JAPANESE // este diplay e o que uso habitualmente
/** * SD CARD * * SD Card support is disabled by default. If your controller has an SD slot, * you must uncomment the following option or it won't work. * */ #define SDSUPPORT // descomentar para ter acesso ao cartao SD
/** * SD CARD: SPI SPEED * * Enable one of the following items for a slower SPI transfer speed. * This may be required to resolve "volume init" errors. */ //#define SPI_SPEED SPI_HALF_SPEED //#define SPI_SPEED SPI_QUARTER_SPEED //#define SPI_SPEED SPI_EIGHTH_SPEED
/** * SD CARD: ENABLE CRC * * Use CRC checks and retries on the SD communication. */ //#define SD_CHECK_AND_RETRY
/** * LCD Menu Items * * Disable all menus and only display the Status Screen, or * just remove some extraneous menu items to recover space. */ //#define NO_LCD_MENUS //#define SLIM_LCD_MENUS
// // ENCODER SETTINGS // // This option overrides the default number of encoder pulses needed to // produce one step. Should be increased for high-resolution encoders. // //#define ENCODER_PULSES_PER_STEP 4
// // Use this option to override the number of step signals required to // move between next/prev menu items. // //#define ENCODER_STEPS_PER_MENU_ITEM 1
/** * Encoder Direction Options * * Test your encoder's behavior first with both options disabled. * * Reversed Value Edit and Menu Nav? Enable REVERSE_ENCODER_DIRECTION. * Reversed Menu Navigation only? Enable REVERSE_MENU_DIRECTION. * Reversed Value Editing only? Enable BOTH options. */
// // This option reverses the encoder direction everywhere. // // Set this option if CLOCKWISE causes values to DECREASE // //#define REVERSE_ENCODER_DIRECTION
// // This option reverses the encoder direction for navigating LCD menus. // // If CLOCKWISE normally moves DOWN this makes it go UP. // If CLOCKWISE normally moves UP this makes it go DOWN. // #define REVERSE_MENU_DIRECTION // inverse o comando do botão do painel de controle
// // Individual Axis Homing // // Add individual axis homing items (Home X, Home Y, and Home Z) to the LCD menu. // //#define INDIVIDUAL_AXIS_HOMING_MENU
// // SPEAKER/BUZZER // // If you have a speaker that can produce tones, enable it here. // By default Marlin assumes you have a buzzer with a fixed frequency. // #define SPEAKER
// // The duration and frequency for the UI feedback sound. // Set these to 0 to disable audio feedback in the LCD menus. // // Note: Test audio output with the G-Code: // M300 S<frequency Hz> P<duration ms> // //#define LCD_FEEDBACK_FREQUENCY_DURATION_MS 2 //#define LCD_FEEDBACK_FREQUENCY_HZ 5000
//============================================================================= //======================== LCD / Controller Selection ========================= //======================== (Character-based LCDs) ========================= //=============================================================================
// // RepRapDiscount Smart Controller. // http://reprap.org/wiki/RepRapDiscount_Smart_Controller // // Note: Usually sold with a white PCB. // #define REPRAP_DISCOUNT_SMART_CONTROLLER // LCD usado na minha impressora
// // ULTIMAKER Controller. // //#define ULTIMAKERCONTROLLER
// // ULTIPANEL as seen on Thingiverse. // //#define ULTIPANEL
// // PanelOne from T3P3 (via RAMPS 1.4 AUX2/AUX3) // http://reprap.org/wiki/PanelOne // //#define PANEL_ONE
// // GADGETS3D G3D LCD/SD Controller // http://reprap.org/wiki/RAMPS_1.3/1.4_GADGETS3D_Shield_with_Panel // // Note: Usually sold with a blue PCB. // //#define G3D_PANEL
// // RigidBot Panel V1.0 // http://www.inventapart.com/ // //#define RIGIDBOT_PANEL
// // Makeboard 3D Printer Parts 3D Printer Mini Display 1602 Mini Controller // https://www.aliexpress.com/item/Micromake-Makeboard-3D-Printer-Parts-3D-Printer-Mini-Display-1602-Mini-Controller-Compatible-with-Ramps-1/32765887917.html // //#define MAKEBOARD_MINI_2_LINE_DISPLAY_1602
// // ANET and Tronxy 20x4 Controller // //#define ZONESTAR_LCD // Requires ADC_KEYPAD_PIN to be assigned to an analog pin. // This LCD is known to be susceptible to electrical interference // which scrambles the display. Pressing any button clears it up. // This is a LCD2004 display with 5 analog buttons.
// // Generic 16x2, 16x4, 20x2, or 20x4 character-based LCD. // #define ULTRA_LCD // estava comentado
//============================================================================= //======================== LCD / Controller Selection ========================= //===================== (I2C and Shift-Register LCDs) ===================== //=============================================================================
// // CONTROLLER TYPE: I2C // // Note: These controllers require the installation of Arduino's LiquidCrystal_I2C // library. For more info: https://github.com/kiyoshigawa/LiquidCrystal_I2C //
// // Elefu RA Board Control Panel // http://www.elefu.com/index.php?route=product/product&product_id=53 // //#define RA_CONTROL_PANEL
// // Sainsmart (YwRobot) LCD Displays // // These require F.Malpartida's LiquidCrystal_I2C library // https://bitbucket.org/fmalpartida/new-liquidcrystal/wiki/Home // //#define LCD_SAINSMART_I2C_1602 //#define LCD_SAINSMART_I2C_2004
// // Generic LCM1602 LCD adapter // //#define LCM1602
// // PANELOLU2 LCD with status LEDs, // separate encoder and click inputs. // // Note: This controller requires Arduino's LiquidTWI2 library v1.2.3 or later. // For more info: https://github.com/lincomatic/LiquidTWI2 // // Note: The PANELOLU2 encoder click input can either be directly connected to // a pin (if BTN_ENC defined to != -1) or read through I2C (when BTN_ENC == -1). // //#define LCD_I2C_PANELOLU2
// // Panucatt VIKI LCD with status LEDs, // integrated click & L/R/U/D buttons, separate encoder inputs. // //#define LCD_I2C_VIKI
// // CONTROLLER TYPE: Shift register panels //
// // 2 wire Non-latching LCD SR from https://goo.gl/aJJ4sH // LCD configuration: http://reprap.org/wiki/SAV_3D_LCD // //#define SAV_3DLCD
//============================================================================= //======================= LCD / Controller Selection ======================= //========================= (Graphical LCDs) ======================== //=============================================================================
// // CONTROLLER TYPE: Graphical 128x64 (DOGM) // // IMPORTANT: The U8glib library is required for Graphical Display! // https://github.com/olikraus/U8glib_Arduino //
// // RepRapDiscount FULL GRAPHIC Smart Controller // http://reprap.org/wiki/RepRapDiscount_Full_Graphic_Smart_Controller // //#define REPRAP_DISCOUNT_FULL_GRAPHIC_SMART_CONTROLLER
// // ReprapWorld Graphical LCD // https://reprapworld.com/?products_details&products_id/1218 // //#define REPRAPWORLD_GRAPHICAL_LCD
// // Activate one of these if you have a Panucatt Devices // Viki 2.0 or mini Viki with Graphic LCD // http://panucatt.com // //#define VIKI2 //#define miniVIKI
// // MakerLab Mini Panel with graphic // controller and SD support - http://reprap.org/wiki/Mini_panel // //#define MINIPANEL
// // MaKr3d Makr-Panel with graphic controller and SD support. // http://reprap.org/wiki/MaKr3d_MaKrPanel // //#define MAKRPANEL
// // Adafruit ST7565 Full Graphic Controller. // https://github.com/eboston/Adafruit-ST7565-Full-Graphic-Controller/ // //#define ELB_FULL_GRAPHIC_CONTROLLER
// // BQ LCD Smart Controller shipped by // default with the BQ Hephestos 2 and Witbox 2. // //#define BQ_LCD_SMART_CONTROLLER
// // Cartesio UI // http://mauk.cc/webshop/cartesio-shop/electronics/user-interface // //#define CARTESIO_UI
// // LCD for Melzi Card with Graphical LCD // //#define LCD_FOR_MELZI
// // SSD1306 OLED full graphics generic display // //#define U8GLIB_SSD1306
// // SAV OLEd LCD module support using either SSD1306 or SH1106 based LCD modules // //#define SAV_3DGLCD #if ENABLED(SAV_3DGLCD) //#define U8GLIB_SSD1306 //#define U8GLIB_SH1106 //estava descomentadada ??? #endif
// // Original Ulticontroller from Ultimaker 2 printer with SSD1309 I2C display and encoder // https://github.com/Ultimaker/Ultimaker2/tree/master/1249_Ulticontroller_Board_(x1) // //#define ULTI_CONTROLLER
// // TinyBoy2 128x64 OLED / Encoder Panel // //#define OLED_PANEL_TINYBOY2
// // MKS MINI12864 with graphic controller and SD support // http://reprap.org/wiki/MKS_MINI_12864 // //#define MKS_MINI_12864
// // Factory display for Creality CR-10 // https://www.aliexpress.com/item/Universal-LCD-12864-3D-Printer-Display-Screen-With-Encoder-For-CR-10-CR-7-Model/32833148327.html // // This is RAMPS-compatible using a single 10-pin connector. // (For CR-10 owners who want to replace the Melzi Creality board but retain the display) // //#define CR10_STOCKDISPLAY
// // ANET and Tronxy Graphical Controller // //#define ANET_FULL_GRAPHICS_LCD // Anet 128x64 full graphics lcd with rotary encoder as used on Anet A6 // A clone of the RepRapDiscount full graphics display but with // different pins/wiring (see pins_ANET_10.h).
// // MKS OLED 1.3" 128 × 64 FULL GRAPHICS CONTROLLER // http://reprap.org/wiki/MKS_12864OLED // // Tiny, but very sharp OLED display // //#define MKS_12864OLED // Uses the SH1106 controller (default) //#define MKS_12864OLED_SSD1306 // Uses the SSD1306 controller
// // Silvergate GLCD controller // http://github.com/android444/Silvergate // //#define SILVER_GATE_GLCD_CONTROLLER
//============================================================================= //============================ Other Controllers ============================ //=============================================================================
// // CONTROLLER TYPE: Standalone / Serial //
// // LCD for Malyan M200 printers. // This requires SDSUPPORT to be enabled // //#define MALYAN_LCD
// // CONTROLLER TYPE: Keypad / Add-on //
// // RepRapWorld REPRAPWORLD_KEYPAD v1.1 // http://reprapworld.com/?products_details&products_id=202&cPath=1591_1626 // // REPRAPWORLD_KEYPAD_MOVE_STEP sets how much should the robot move when a key // is pressed, a value of 10.0 means 10mm per click. // //#define REPRAPWORLD_KEYPAD //#define REPRAPWORLD_KEYPAD_MOVE_STEP 10.0
//============================================================================= //=============================== Extra Features ============================== //=============================================================================
// @section extras
// Increase the FAN PWM frequency. Removes the PWM noise but increases heating in the FET/Arduino //#define FAST_PWM_FAN
// Use software PWM to drive the fan, as for the heaters. This uses a very low frequency // which is not as annoying as with the hardware PWM. On the other hand, if this frequency // is too low, you should also increment SOFT_PWM_SCALE. //#define FAN_SOFT_PWM
// Incrementing this by 1 will double the software PWM frequency, // affecting heaters, and the fan if FAN_SOFT_PWM is enabled. // However, control resolution will be halved for each increment; // at zero value, there are 128 effective control positions. #define SOFT_PWM_SCALE 0
// If SOFT_PWM_SCALE is set to a value higher than 0, dithering can // be used to mitigate the associated resolution loss. If enabled, // some of the PWM cycles are stretched so on average the desired // duty cycle is attained. //#define SOFT_PWM_DITHER
// Temperature status LEDs that display the hotend and bed temperature. // If all hotends, bed temperature, and target temperature are under 54C // then the BLUE led is on. Otherwise the RED led is on. (1C hysteresis) //#define TEMP_STAT_LEDS
// M240 Triggers a camera by emulating a Canon RC-1 Remote // Data from: http://www.doc-diy.net/photo/rc-1_hacked/ //#define PHOTOGRAPH_PIN 23
// SkeinForge sends the wrong arc g-codes when using Arc Point as fillet procedure //#define SF_ARC_FIX
// Support for the BariCUDA Paste Extruder //#define BARICUDA
// Support for BlinkM/CyzRgb //#define BLINKM
// Support for PCA9632 PWM LED driver //#define PCA9632
/** * RGB LED / LED Strip Control * * Enable support for an RGB LED connected to 5V digital pins, or * an RGB Strip connected to MOSFETs controlled by digital pins. * * Adds the M150 command to set the LED (or LED strip) color. * If pins are PWM capable (e.g., 4, 5, 6, 11) then a range of * luminance values can be set from 0 to 255. * For Neopixel LED an overall brightness parameter is also available. * * *** CAUTION *** * LED Strips require a MOSFET Chip between PWM lines and LEDs, * as the Arduino cannot handle the current the LEDs will require. * Failure to follow this precaution can destroy your Arduino! * NOTE: A separate 5V power supply is required! The Neopixel LED needs * more current than the Arduino 5V linear regulator can produce. * *** CAUTION *** * * LED Type. Enable only one of the following two options. * */ //#define RGB_LED //#define RGBW_LED
#if ENABLED(RGB_LED) || ENABLED(RGBW_LED) #define RGB_LED_R_PIN 34 #define RGB_LED_G_PIN 43 #define RGB_LED_B_PIN 35 #define RGB_LED_W_PIN -1 #endif
// Support for Adafruit Neopixel LED driver //#define NEOPIXEL_LED #if ENABLED(NEOPIXEL_LED) #define NEOPIXEL_TYPE NEO_GRBW // NEO_GRBW / NEO_GRB - four/three channel driver type (defined in Adafruit_NeoPixel.h) #define NEOPIXEL_PIN 4 // LED driving pin on motherboard 4 => D4 (EXP2-5 on Printrboard) / 30 => PC7 (EXP3-13 on Rumba) #define NEOPIXEL_PIXELS 30 // Number of LEDs in the strip #define NEOPIXEL_IS_SEQUENTIAL // Sequential display for temperature change - LED by LED. Disable to change all LEDs at once. #define NEOPIXEL_BRIGHTNESS 127 // Initial brightness (0-255) //#define NEOPIXEL_STARTUP_TEST // Cycle through colors at startup #endif
/** * Printer Event LEDs * * During printing, the LEDs will reflect the printer status: * * - Gradually change from blue to violet as the heated bed gets to target temp * - Gradually change from violet to red as the hotend gets to temperature * - Change to white to illuminate work surface * - Change to green once print has finished * - Turn off after the print has finished and the user has pushed a button */ #if ENABLED(BLINKM) || ENABLED(RGB_LED) || ENABLED(RGBW_LED) || ENABLED(PCA9632) || ENABLED(NEOPIXEL_LED) #define PRINTER_EVENT_LEDS #endif
/** * R/C SERVO support * Sponsored by TrinityLabs, Reworked by codexmas */
/** * Number of servos * * For some servo-related options NUM_SERVOS will be set automatically. * Set this manually if there are extra servos needing manual control. * Leave undefined or set to 0 to entirely disable the servo subsystem. */ //#define NUM_SERVOS 3 // Servo index starts with 0 for M280 command
// Delay (in milliseconds) before the next move will start, to give the servo time to reach its target angle. // 300ms is a good value but you can try less delay. // If the servo can't reach the requested position, increase it. #define SERVO_DELAY { 300 }
// Only power servos during movement, otherwise leave off to prevent jitter //#define DEACTIVATE_SERVOS_AFTER_MOVE
#endif // CONFIGURATION_H…
Adicionado por Richard Falcos ao 11:36 em 8 dezembro 2019
ESC/POS é sistema de comandos da impressora desenvolvido pela EPSON. Permite-lhe controlar diretamente todas as funções da impressora. Usar os comandos com o controlador, pode usar uma função que não seja fornecida pelo controlador.
Comparado com a utilização dos controladores, a utilização dos comandos é difícil pois precisa conhecer as especificações detalhadas e sobre como combinar os comandos.
De modo a utilizar os comandos ESC/POS , deve assinar o nosso contrato de confidencialidade e obter o guia de programação da aplicação ESC/POS. Para mais informações, por favor contacte o seu representante."
No google é possível encontrar essa documentação!!!
http://nicholas.piasecki.name/blog/wp-content/uploads/2009/12/ESC-POS-Programming-Guide.pdf
Aqui um pouco do código que fiz e estou usando para testar minha impressora, um Epson TM-T88 Serial
Saudações Rapaziada.
#include <SoftwareSerial.h>SoftwareSerial printer(2,3); // Pino TX, RX do max232 que converte TTL para Serial Impressora. http://www.sparkfun.com/images/tutorials/BeginningEmbedded/4-UART/U...
void setup(){
Serial.begin(9600);
printer.begin(9600);
}
void loop() {
// Imprime o valor dentro de codBuffer a cada 500milisegundos
delay(500); codeHeight(100); //ALTURA DO COD printPosition(2); //POSICAO DA IMPRESSAO DECIMAL: 2=Abaixo do Codigo codeWidth(3); //LARGURA DO CODIGO. Valor entre 0 e 6 fontTipe(0); //TIPO DA FONTE. Valor entre 0 e 3
printer.println("(: RODRIGO :)"); //Imprime o valor e clama uma nova linha char codBuffer[12] = {'9','9','9','9','9','9','9','9','9','9','9','9'}; //Imprime Array // ===========PRINT BAR CODE ============= // printer.write(byte(29)); //GS printer.write(byte(107)); //k printer.write(byte(0)); //m for (byte i=0; i<sizeof(codBuffer);i++){ printer.write(byte(codBuffer[i])); } printer.write(byte(0)); //Terminador // ===========END PRINT BAR CODE ============= // paperFeed(5); //Avanca 5 linhas em branco cutPaper(); //Corta papel } // ***************** CUTPAPER ******************** // void cutPaper(){ //Corta papel da impressora printer.write(byte(0x1D)); printer.write(byte(0x56)); printer.write(byte(0x00)); } // ***************** CODEHEIGHT ******************** // void codeHeight(byte val){ //ALTURA DO CODIGO printer.write(byte(0x1D)); //GS printer.write(byte(0x68)); //h printer.write(byte(val)); //Altura do Cod Range[0-255] } // ***************** PAPERFEED ******************** // void paperFeed(byte val){ //Avanca Papel qntidade de linhas especificadas na chamda da funcao for(byte i=0;i<val;i++){ printer.write(byte(0x0A)); } } // ***************** ROTATE ******************** // void rotatePrint(){ //ROTAR printer.write(byte(0x1B)); //ESC printer.write(byte(0x56)); //V printer.write(byte(49)); //n } // ***************** POSICAO DA IMPRESSAO DECIMAL ******************** // void printPosition(byte val){ //POSICAO DO CODIGO DEC printer.write(byte(0x1D)); //GS printer.write(byte(0x48)); //H printer.write(byte(val)); //n /* ============================= / [0] Não impresso [1] Acima do codigo [2] Abaixo do Codigo [3] Acima e Abaixo do Codigo / ============================= */ } // ***************** DIRECAO DA IMPRESSAO ******************** // void printDirection(int val){ //DIRECAO DA IMPRESSAO printer.write(byte(0x1B)); //ESC printer.write(byte(0x54)); //T printer.write(byte(val)); //n /* ============================= / [0] Esquerda para a Direita [1] Base para o Topo [2] Direita para Esquerda [3] Topo para Base / ============================= */ } // ***************** FONTE ******************** // void fontTipe(int val){ //DIRECAO DA IMPRESSAO printer.write(byte(0x1D)); //GS printer.write(byte(0x66)); //f printer.write(byte(val)); //n /* ============================= / [0] Fonte A [1] Fonte B [2] Fonte c / ============================= */ } // ***************** CODE WIDHT ******************** // void codeWidth(int val){ //LARGURA DO CODIGO printer.write(byte(0x1D)); //GS printer.write(byte(0x77)); //w printer.write(byte(val)); //n 2< n <6, 68< n <76 } // ***************** CODE PRINT ******************** // void setArea(){ printer.write(byte(0x1B)); //GS printer.write(byte(0x57)); //w printer.write(byte(255)); //xl printer.write(byte(255)); //xh printer.write(byte(255)); //yl printer.write(byte(255)); //yh printer.write(byte(104)); //dxl printer.write(byte(1)); //dxh printer.write(byte(126)); //dyl printer.write(byte(6)); //dyh } // ***************** VERTICAL PRINT ******************** // void setMotionUnit(){ printer.write(byte(0x1D)); //GS printer.write(byte(0X50)); //P printer.write(byte(0)); //x printer.write(byte(0)); //y }…
Adicionado por Rodrigo Daniel ao 13:34 em 4 janeiro 2013