trolado por um Arduino Nano. Normalmente encontra-se na WEB, inúmeros circuitos desses, mas somente controlando os pinos de sentido de rotação (DIR) e dos pulsos dos passos (STEP).
Resolvi fazer uma montagem de teste usando todas as portas de controle do Módulo A4988 ! Outra dúvida minha era se eu conseguiria usar o meu Motor NEMA17 Unipolar de seis fios no modo Bipolar, já que o chip A4988 foi projetado para motores Bipolares somente. E tudo funcionou perfeitamente.
Esse é o diagrama da minha montagem :
Observações importantes :
- A tensão de alimentação do Motor deve ser entre 8V e 35 V (não pode usar motores com 5V somente).
- A corrente não pode ultrapassar 2A em cada bobina do motor.
- Use um capacitor (C1) de no mínimo 100 uF para filtrar ruidos na alimentação do motor.
- Use um capacitor (C2) de no mínimo 10 uF para filtrar ruidos na alimentação do chip A4988.
- Não se esqueça de conectar o terra do Arduino.
Vejam que eu usei somente quatro fios do motor, já que estou usando a ligação Bipolar. Os fios dos terminais centrais dos enrolamentos devem ficar isolados do circuito - Fio 2 (branco) e Fio 5 (preto).
O Módulo Driver A4988 tem um potênciomentro (POT) de ajuste de corrente máxima. Se a corrente ultrapassar o limite, o chip é desativado para proteção dos circuitos. Explicarei como isso funciona e como ajustar em outro tópico. (não mexa ainda nesse ajuste) . No meu módulo ele já veio ajustado para corrente máxima de 1,25 ampéres.
Criei um Sketch para permitir o teste de todos os pinos de controle / funções do Módulo A4988. Usei oito portas digitais do Arduino. A designação de cada porta foi escolha minha. Nada impede que você utilize outras portas, desde que altere as ligações e o seu sketch de acordo com o novo circuito.
Esse é o Sketch de teste. Fiz ele com propósitos didáticos. Como eu ainda não sei como criar bibliotecas para o Arduino, usei uma programação estruturada com várias funções. Se acharem interessante, poderemos até criar uma biblioteca específica. O Sketch pemite o uso de todos os modos de passo : Full, Half, Micro-passo de 1/4, Micro-passo de 1/8 e Micro-passo de 1/16. Permite também que configure a frequência dos pulsos (passos), a quantidade de passos,o sentido de rotação, etc.
Anexei o arquivo do Sketch : A4988a.INO
// Controle de Motor de Passo NEMA17 com Modulo driver A4988 // http://labdegaragem.com/forum/topics/tutorial-arduino-motor-de-pass...
// Motor Minebea NEMA 17 Unipolar / Modulo A4988 / Arduino Nano / IDE 1.6.7
// OBS: Motor Unipolar 6 fios configurado como Bipolar
// Gustavo Murta 02/abr/2016
// Definições das Portas Digitais do Arduino
int RST = 8; // Porta digital D08 - reset do A4988 int SLP = 9; // Porta digital D09 - dormir (sleep) A4988
int ENA = 7; // Porta digital D07 - ativa (enable) A4988
int MS1 = 4; // Porta digital D04 - MS1 do A4988
int MS2 = 5; // Porta digital D05 - MS2 do A4988
int MS3 = 6; // Porta digital D06 - MS3 do A4988
int DIR = 3; // Porta digital D03 - direção (direction) do A4988
int STP = 2; // Porta digital D02 - passo(step) do A4988
int atraso = 0; // Atraso no pulso em microsegundos
float FREQ = 200; // Frequências dos pulsos (100.7 Hz medido com scope = 100 Hz)
boolean sentido = true; // Variavel de sentido
int CONTADOR = 200; // Número de pulsos (passos por volta)
// FULL = 200 passos / HALF = 400 passos / P1_4 = 800 passos / P1_8 = 1600 passos / P1_16 = 3200 passos
void setup() {
Serial.begin(9600);
DDRD = DDRD | B11111100; // Configura Portas D02 até D07 como saída
digitalWrite(ENA, HIGH); // Desativa o chip A4988
FULL() ; // Configura modo de avanço do motor FULL, HALF, P1_4, P1_8 ou P1_16
DDRB = 0x0F; // Configura Portas D08,D09,D10 e D11 como saída
digitalWrite(SLP, HIGH); // Desativa sleep do A4988
rst_A4988(); // Reseta o chip A4988
digitalWrite(ENA, LOW); // Ativa o chip A4988
FREQUENCIA(); // Calcula o período do sinal STEP
//Serial.println(atraso) ; // Imprime na Console, o tempo em microsegundos
}
void rst_A4988() {
digitalWrite(RST, LOW); // Realiza o reset do A4988
delay (10); // Atraso de 10 milisegundos
digitalWrite(RST, HIGH); // Libera o reset do A4988
}
void HOR() // Configura o sentido de rotação do Motor {
digitalWrite(DIR, HIGH); // Configura o sentido HORÁRIO
}
void AHR() // Configura o sentido de rotação do Motor {
digitalWrite(DIR, LOW); // Configura o sentido ANTI-HORÁRIO
}
void PASSO() // Pulso do passo do Motor {
digitalWrite(STP, LOW); // Pulso nível baixo
delayMicroseconds (atraso); // Atraso de X microsegundos
digitalWrite(STP, HIGH); // Pilso nível alto
delayMicroseconds (atraso); // Atraso de X microsegundos
}
void FREQUENCIA() // Configura quantos pulsos por segundo (Hz) {
atraso = 1000000 / (2*FREQ); // calculo do tempo de atraso (1/2 periodo) em us
}
void FULL() {
digitalWrite(MS1, LOW); // Configura modo Passo completo (Full step)
digitalWrite(MS2, LOW);
digitalWrite(MS3, LOW);
}
void HALF() {
digitalWrite(MS1, HIGH); // Configura modo Meio Passo (Half step)
digitalWrite(MS2, LOW);
digitalWrite(MS3, LOW);
}
void P1_4() {
digitalWrite(MS1, LOW); // Configura modo Micro Passo 1/4
digitalWrite(MS2, HIGH);
digitalWrite(MS3, LOW);
}
void P1_8() {
digitalWrite(MS1, HIGH); // Configura modo Micro Passo 1/8
digitalWrite(MS2, HIGH);
digitalWrite(MS3, LOW);
}
void P1_16() {
digitalWrite(MS1, HIGH); // Configura modo Micro Passo 1/16
digitalWrite(MS2, HIGH);
digitalWrite(MS3, HIGH);
}
void TesteMotor() {
HOR();
for(int i=0; i <= CONTADOR; i++) // Incrementa o Contador
{
PASSO(); // Avança um passo no Motor
}
delay (750) ; // Atraso de 500 mseg
AHR();
for(int i=0; i <= CONTADOR; i++) // Incrementa o Contador
{
PASSO(); // Avança um passo no Motor
}
delay (1500) ; // Atraso de 500 mseg
}
void loop()
{
FULL();
FREQ = 200;
FREQUENCIA();
CONTADOR = 200;
Serial.print(atraso);
Serial.println(" us Full, 200 passos, 200 Hz");
Serial.println();
TesteMotor();
HALF();
FREQ = 600;
FREQUENCIA();
CONTADOR = 400;
Serial.print(atraso);
Serial.println(" us Half, 200 passos, 600 Hz");
Serial.println();
TesteMotor();
P1_4(); FREQ = 1600;
FREQUENCIA();
CONTADOR = 800;
Serial.print(atraso);
Serial.println(" us Micro 1/4, 800 passos, 1600 Hz");
Serial.println();
TesteMotor();
P1_8(); FREQ = 3600;
FREQUENCIA();
CONTADOR = 1600;
Serial.print(atraso);
Serial.println(" us Micro 1/8, 1600 passos, 3600 Hz");
Serial.println();
TesteMotor();
P1_16(); FREQ = 6600;
FREQUENCIA();
CONTADOR = 3200;
Serial.print(atraso);
Serial.println(" us Micro 1/16, 3200 passos, 6600 Hz");
Serial.println();
TesteMotor();
}
Para que possam ver como o teste é realizado estou divulgando esse video , onde estou rodando o mesmo Sketch.
Motor NEMA17 + Driver A4988 - teste do Motor
…
oop ( serial monitor) e se iniciam corretamente. Não sou programador, e tenho aprendido por aqui mesmo. (Obs: algumas bibliotecas se referem a módulos chineses alternativos que tenho e são um pouco diferente dos demais módulos - DHT11, COMPASS HMC5883 ). Ainda não comprei o motor com pás para medir a velocidade do vento, e o sensor de chuva. Mas já deixo instalado o sensor sônico para o pluviômetro, pode ser usado com cartão SD( o meus queimei por descuido, mas estava nesta programação, retirei) e o conjunto ficará em um balão amarado, que subirá aos poucos, poderá girar em seu eixo e inclinar conforme o vento. Também poderá ser usado em drones, por quem quiser usar o projeto.
Por favor vejam que o foco inicial é saber como testar no setup() se eles estão ok.
Atenção: Qualquer um que usar balões deve ter autorização de manejo de acordo com o estado e instituição de ensino, não deve realizar qualquer teste em condições de céu nublado ou chuva sem tomar orientação sobre os riscos, não me responsabilizo pelas tentativas de teste que causem risco de morte e contravenção da lei dos balões RJ.
// Marcelo da Silva Santos (Designer, esp. animador, estudante de engenharia mecanica)// Estacao meteriologica feita em casa / HOME MADE Meteriologoc station prototype// Portugues - Brasil - BR_pt (Lingua).// Rio de Janeiro 22:09 / Sexta-feira / 09 / Agosto / 2019.// 1.0v Dados livres. Obg a todos / FreeData. Tks Everybody!// Rascunho na memoria do uno / UNO Sketch memory 88%...!!! :(
#include <Ultrasonic.h>#define pino_trigger A0#define pino_echo A1Ultrasonic ultrasonic(pino_trigger, pino_echo);float cmMsec, inMsec;long microsec = ultrasonic.timing();//----------------------------------------------------------------------------------#include <dht.h>#define pinoDHT11 9dht sensorDHT11;//----------------------------------------------------------------------------------#include <Adafruit_Sensor.h> #include <Adafruit_BMP280.h> float PressaoDoDia;int Atm = 0; Adafruit_BMP280 bmp; //----------------------------------------------------------------------------------
#include <Wire.h>#include <MechaQMC5883.h>MechaQMC5883 qmc; int x, y, z; int azimuth;
//----------------------------------------------------------------------------------//#include <SD.h>
//Sd2Card SDcard;//SdVolume volume;
//const int chipSelect = 10; //----------------------------------------------------------------------------------#include <DS3232RTC.h>
const int MPU=0x68; int AcX,AcY,AcZ,Tmp,GyX,GyY,GyZ;
long ContadorLoop = 0; // CONTADOR DE LOOP(Tipo de Timer primitivo).int Ciclos =0; // contador de ciclos cheios do contador de loop.//----------------------------------------------------------------------------------
void setup(){ Serial.begin(9600); Wire.begin(); setSyncProvider(RTC.get); Wire.beginTransmission(MPU); Wire.write(0x6B); Wire.write(0); Wire.endTransmission(true); cmMsec = ultrasonic.convert(microsec, Ultrasonic::CM); inMsec = ultrasonic.convert(microsec, Ultrasonic::IN); if(!Serial) // 1 { Serial.println("Erro ao iniciar Serail! Verifique as conexões."); Serial.println("Verifique o Modulo, conexoes e reinicie o Arduino..."); Serial.print("Erro no Loop: "); Serial.println(ContadorLoop); } else { Serial.println("Serial iniciado!"); Serial.print("Inicio no Loop: "); Serial.println(ContadorLoop); } if(!bmp.begin(0x76)) // 2 { Serial.println("Sensor BMP280 não foi identificado! Verifique as conexões."); Serial.println("Verifique o Modulo, conexoes e reinicie o Arduino..."); Serial.print("Erro no Loop: "); Serial.println(ContadorLoop); } else { Serial.println("Sensor BMP280 foi identificado!");Serial.print("Inicio no Loop: "); Serial.println(ContadorLoop); } if(timeStatus() != timeSet) // 3 { Serial.println("Impossivel sincronismo com RTC"); Serial.println("Verifique o Modulo, conexoes e reinicie o Arduino..."); Serial.print("Erro no Loop: "); Serial.println(ContadorLoop); } else { Serial.println("RTC Esta definindo o tempo do sistema"); Serial.println("Módulo RTC foi identificado!"); Serial.print("Inicio no Loop: "); Serial.println(ContadorLoop); } if(!MPU, 0x6B) // 4 { Serial.println("Impossivel sincronismo com MPU6050"); Serial.println("Verifique o Modulo, conexoes e reinicie o Arduino..."); Serial.print("Erro no Loop: "); Serial.println(ContadorLoop); } else { Serial.println("Sincronismo com MPU6050, ok!"); Serial.print("Inicio no Loop: "); Serial.println(ContadorLoop); } if(inMsec=0) // 5 { Serial.println("Nenhum pulso detectado de Ultrasonico!"); Serial.println("Esperando para teste, sincronismo com Ultrasonic"); delay(2500); Serial.println("Novo teste iniciado!"); cmMsec = ultrasonic.convert(microsec, Ultrasonic::CM); inMsec = ultrasonic.convert(microsec, Ultrasonic::IN); if((inMsec=0) && (cmMsec=0 )) { Serial.println("Impossivel sincronismo com Ultrasonic"); Serial.println("Verifique o Modulo, conexoes e reinicie o Arduino..."); Serial.print("Erro no Loop: "); Serial.println(ContadorLoop); } else { Serial.println("Detectado sincronismo com Ultrasonic no segundo teste!"); } } else { Serial.println("Sincronismo com Ultrasonic, ok!"); Serial.print("Inicio no Loop: "); Serial.println(ContadorLoop); } sensorDHT11.read11(pinoDHT11); if((sensorDHT11.humidity=0) && ((sensorDHT11.temperature)=0)) // 6 { sensorDHT11.read11(pinoDHT11); delay(2500); if((sensorDHT11.humidity=0) && ((sensorDHT11.temperature)=0)) { Serial.println("Impossivel sincronismo com DHT_11"); Serial.println("Verifique o Modulo, conexoes e reinicie o Arduino..."); Serial.print("Erro no Loop: "); Serial.println(ContadorLoop); } else { Serial.println("Sincronismo com DHT_11, ok!"); Serial.print("Inicio no Loop: "); Serial.println(ContadorLoop); } } else { Serial.println("Sincronismo com DHT_11, ok!"); Serial.print("Inicio no Loop: "); Serial.println(ContadorLoop); } if((x=-1) && ( y=-1)) // 7 { x=0; y=0; z=0; delay(2500); if((x=-1) && (y=-1)) { Serial.println("Impossivel sincronismo com Bussola!"); Serial.println("Verifique o Modulo, conexoes e reinicie o Arduino..."); Serial.print("Erro no Loop: "); Serial.println(ContadorLoop); } else { Serial.println("Sincronismo com a Busola na segundo teste, ok!"); Serial.print("Inicio no Loop: "); Serial.println(ContadorLoop); } } else { Serial.println("Sincronismo com a bussola, ok!"); Serial.print("Inicio no Loop: "); Serial.println(ContadorLoop); }}
void loop(){ Serial.println("----------------------------------------------------------------------------------"); // ________________________ RTC ___________________________________________________________________________________________________ digitalClockDisplay(); // _______________________ DHT 11 _________________________________________________________________________________________________ sensorDHT11.read11(pinoDHT11); // _______________________ BMP 280 ________________________________________________________________________________________________ PressaoDoDia = 1013,25; // pressao ao nivel do mar, // ajustar este valor pela internet no mesmo dia. // _______________________ BUSSOLA ________________________________________________________________________________________________ qmc.read(&x, &y, &z,&azimuth); // _______________________ MPU 6050 _______________________________________________________________________________________________ Wire.beginTransmission(MPU); Wire.write(0x3B); Wire.endTransmission(false); Wire.requestFrom(MPU,14,true); AcX=Wire.read()8|Wire.read(); //0x3B (ACCEL_XOUT_H) & 0x3C (ACCEL_XOUT_L) AcY=Wire.read()8|Wire.read(); //0x3D (ACCEL_YOUT_H) & 0x3E (ACCEL_YOUT_L) AcZ=Wire.read()8|Wire.read(); //0x3F (ACCEL_ZOUT_H) & 0x40 (ACCEL_ZOUT_L) Tmp=Wire.read()8|Wire.read(); //0x41 (TEMP_OUT_H) & 0x42 (TEMP_OUT_L) GyX=Wire.read()8|Wire.read(); //0x43 (GYRO_XOUT_H) & 0x44 (GYRO_XOUT_L) GyY=Wire.read()8|Wire.read(); //0x45 (GYRO_YOUT_H) & 0x46 (GYRO_YOUT_L) GyZ=Wire.read()8|Wire.read(); //0x47 (GYRO_ZOUT_H) & 0x48 (GYRO_ZOUT_L) // _____________________________ Escrevendo no Serial _____________________________________________________________________________ if (ContadorLoop>0) { Serial.println("Iniciando Sistema, preparando CAIXA PRETA!"); Serial.print("INICIO DE Loop: "); Serial.println(ContadorLoop); Serial.println("-----------------------------Ultrasonic--------------------------------------------"); Serial.print("Distancia em cm: "); Serial.print(cmMsec); Serial.print(" - Distancia em polegadas: "); Serial.println(inMsec); Serial.println("-----------------------------DHT11------------------------------------------------"); Serial.print("Umidade: "); Serial.print(sensorDHT11.humidity); Serial.print("%"); Serial.print(" - Temperatura_1: "); Serial.print(sensorDHT11.temperature,0); Serial.println("C"); Serial.println("----------------------------BMP 280-----------------------------------------------"); Serial.print("Temperatura_2: "); Serial.print(bmp.readTemperature()); Serial.print(" *C (Grau Celsius)"); Serial.print(" - Pressao: "); Serial.print(bmp.readPressure()); Serial.print(" Pa (Pascal)"); Serial.print(" - Atmosfera: "); Atm = (((bmp.readPressure())/PressaoDoDia),1); Serial.println(Atm); Serial.println("-----------------------------Bussola----------------------------------------------"); Serial.print("x: "); Serial.print(x); Serial.print(" - y: "); Serial.print(y); Serial.print(" - z: "); Serial.print(z); Serial.print(" ROTACAO EM RELACAO AO NORTE: "); Serial.print(azimuth); Serial.println(); Serial.println("-----------------------------MPU 6050---------------------------------------------"); Serial.print("AcX = "); Serial.print(AcX); Serial.print(" | AcY = "); Serial.print(AcY); Serial.print(" | AcZ = "); Serial.print(AcZ); Serial.print(" | Tmp = "); Serial.print(Tmp/340.00+36.53); Serial.print(" | GyX = "); Serial.print(GyX); Serial.print(" | GyY = "); Serial.print(GyY); Serial.print(" | GyZ = "); Serial.println(GyZ); Serial.println("----------------------------------------------------------------------------------"); } if (ContadorLoop >=2147483646) { ContadorLoop=0; Ciclos=Ciclos+1; Serial.println(ContadorLoop); Serial.println(Ciclos); } Serial.print("FIM DE Loop: "); Serial.println(ContadorLoop); Serial.println("----------------------------------------------------------------------------------"); Serial.println(" "); Serial.println(" "); ContadorLoop = ContadorLoop + 1; } // _____________________________ Escrevendo no Serial Fim _________________________________________________________________________
void digitalClockDisplay(){ 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){ Serial.print(':'); if(digits < 10) { Serial.print('0'); Serial.print(digits); }}…
ores e do "Fim de Curso", pois senão seu Sistema provavelmente não será "robusto" o suficiente para os problemas que ocorrem quando os "fios" são bem longos (e veja: o tratamento que fiz, é o básico).
Agora sobre o código, o do último post está bastante preparado pra atender as requisições que vc mencionou, e na realidade faltam apenas alguns "acréscimos" pra isso.
No entanto, eu percebo uma certa dificuldade em expressar com mais clareza estas requisições, e provavelmente isso ocorre justamente devido à questão "verde" que mencionei antes. Mas com uma pequena ajuda facilmente isto é superado, e vou te mostrar como.
Mas antes entenda que numa primeira instância, não é necessário que vc descreva a "real forma" que constitui seu Sistema, ou seja, não é necessário saber se são tratores ou se são outras coisas, ou se o líquido é água ou outra coisa. Na forma como estamos fazendo aqui via internet (e fórum), o que é preciso saber é quais são os elementos "medidos" pelo Sistema, e isso vc deixou claro: dois Sensores de Fluxo e um "Fim de Curso". E claro também como o Sistema deve funcionar.
Veja, está claro que existem dois Fluxos, e que a vazão destes é indicada por dois Sensores de Fluxo. O Sistema então deve medir esta vazão (a partir dos pulsos dos Sensores), exibir estes valores no Display, e também calcular as Médias em um certo período de tempo, sendo estas Médias também exibidas no Display. Isto já está sendo feito no Sistema que postei (o primeiro tinha apenas um Sensor de Fluxo, mas o segundo Sistema já tem os dois). Então o que falta agora é processar de forma adequada estas informações. Então vou dar um exemplo de como se descreve isto de forma que se possa usar estas informações no código, e assim vc entendendo isso, poderá postar dessa forma aqui, sem deixar dúvidas de como a coisa deve ser de fato.
Então segue um exemplo da descrição do seu Sistema (por favor, leia com atenção, pois a maior parte da descrição, acredito ser como seu Sistema deve funcionar):
1) dois Sensores indicam o Fluxo de Líquidos. São sensores semelhantes ao "YF-S201C". Os sinais dos Sensores são aplicados aos pinos "2" e "3" de um Arduino UNO, a fim de medir o Fluxo em cada sensor, em Litros/segundo.
2) há também no Sistema, uma chave (ou botão) "Fim de Curso", conectada ao pino "4" do Arduino. A chave será acionada após um certo tempo "Ta" (abreviando "Tempo de avaliação"), e este tempo "Ta" é contado a partir do momento que as medições são iniciadas (ou seja, praticamente após o Arduino ser ligado).
3) os Fluxos dos dois Sensores, são exibidos no Display a cada segundo. Também é exibido no Display, uma contagem de tempo, que sempre inicia em 0 (zero) segundos, e vai até 59 segundos. Esta contagem volta a zero após passado 1 minuto, e a contagem em segundos se repete.
4) quando é completado 1 minuto, é calculada a Média dos Fluxos neste período de tempo (60 segundos). As Médias de cada Fluxo são então exibidas no Display, e esta exibição dura alguns segundos (por exemplo 5 segundos).
5) quando o "Fim de Curso" é acionado, são então calculadas em Litros, as quantidades de líquido de cada Fluxo. Então, a quantidade do Sensor 2 é subtraída da quantidade do Sensor 1, obtendo-se assim uma diferença entre as duas quantidades. Vamos chamar esta diferença de "dQ" (abreviando "diferença das Quantidades"). Então este valor "dQ" é exibido no Display (por algum tempo).
6) uma vez calculado o valor "dQ", ele é multiplicado por um fator "K" (seria o "238" do exemplo que vc descreveu Franciel). Vamos chamar este resultado que foi calculado, de "QT" (abreviatura de "Quantidade Total"). Então este valor "QT" é exibido no Display (também por um certo tempo).
7) então após este ciclo completo, o Sistema reinicia tudo, zerando a quantidade de Líquido dos dois Fluxos, e repetindo o ciclo.
Veja Franciel, uma descrição dessa forma permite que o código execute precisamente o comportamento descrito. Então veja como ela é importante.
Claro, para a descrição que coloquei, apenas segui o que seu código original estava fazendo e inclui as informações de funcionamento que vc passou até aqui.
Mas não sei se é exatamente isso, porque é apenas minha interpretação das coisas. E vc é quem pode dizer como realmente o Sistema deve se comportar.
Assim, aguardo suas informações a respeito, para que eu possa aplicar ao código e postá-lo aqui, incluindo uma Simulação do funcionamento.
Uma questão: vc não acha que seria interessante ao invés de usar um Display LCD 16x2, usar-se o mesmo tipo de Display LCD I2C, porém aquele de 20x4, pois assim teria mais caracteres em uma linha e duas linhas a mais, o que facilitaria a exibição dos dados.
Veja se é interessante também, incluir um "Módulo Buzzer", desses pra Arduino que todo mundo usa. Assim, quando o Sistema completar um ciclo e exibir os resultados, o Buzzer seria acionado indicando que os dados estão disponíveis. Você pode inclusive acrescentar um Botão, e após um ciclo terminar e este Botão ser acionado, então o Sistema reinicia todo o processo (ou ciclo), sem precisar desligar o Arduino.
Fico no aguardo...
Abrçs,
Elcids…
Adicionado por Elcids Chagas ao 13:34 em 2 abril 2020
do Terminal do Arduino (estas marcações de tempo são fundamentais, mas eu esqueci de colocar algo assim no código, para o caso do "timestamp" do Terminal estar desligado).
Vamos então às conclusões dessa análise "preliminar":
O "travamento" que ocorreu conforme vc descreveu, eu acredito que seja por causa do uso da função "maintain" da "UIP", e explico isso mais adiante.
Os dados impressos no Terminal, mostram que ocorrem momentos que o "Cliente" (o Arduino) não conseguiu se conectar ao "Host" (o Modem), mas logo em seguida conseguiu a conexão, e aí o "Host' respondeu de acordo. Estas falhas ocorrem em três momentos, e nos dois primeiros, o Sistema conseguiu se recuperar. Mas na terceira, vemos que a última mensagem foi "não recebeu o Sinal", e depois disso nenhuma msg foi "impressa". Veja a sequência que ocorre:
a) 25 respostas OK do Host, num período de 13 segundos.
b) 2 falhas de conexão do Cliente, num período menor que 0.5 segundo.
c) 14 respostas OK do Host, num período de 7 segundos.
d) 2 falhas de conexão do Cliente, num período menor que 0.5 segundo.
e) 15 respostas OK do Host, num período de 8 segundos.
f) 1 falha de conexão do Cliente, então "trava", e não há mais respostas.
Como se vê, embora o período de teste não seja muito grande, parece que estava se formando um padrão de comportamento. Lembrando que no teste, eram feitas requisições a cada 250 ms (ou seja, 4 vezes por segundo).
Uma coisa muito importante, é que a RAM "livre" ficou estável o tempo todo, o que é um ótimo sinal, pois indica que a LIB "UIP" não está "largando" objetos no "Heap" do Arduino (se estivesse "largando" poderia levar a um "crash" do Sistema). E pela quantidade total de requisições, esta conclusão é praticamente definitiva sobre esta versão do código.
As falhas de conexão do "Cliente", são evidentes porque naqueles momentos não são impressas as msgs de RAM "free" de (3) a (5), mas sempre foi impressa a msg (6). E não foi ocorrência do "timeout" que eu implementei, pois para isso teriam que ter sido impressas as msgs de (3) até (5). Então sobre isso não há dúvida.
Então o que causou o "travamento" ??? Eu tenho um palpite, e ele pode ser evidenciado na figura a seguir, que mostra uma observação que "fizeram" no código fonte da LIB "UIP", especificamente na função "maintain" (veja principalmente o texto que eu marquei em amarelo) :
(clique na figura para "zoom")
Eu suspeito que o tratamento de algum desses "IP events", tenha falhado por algum motivo, e como não implementaram um "timeout" nestes casos, a função "maintain" não retorna (como explicado na figura anterior), causando o Sistema travar. Pode ser um bug da "UIP", por que provavelmente o "maintain" é muito pouco usado (eu realmente nunca vi alguém usando isso no "UIP") e então talvez ninguém tenha detectado isso (ou detectaram e deixaram pra lá).
Ocorre que como o "Ethernet.begin" não está mais no "loop" do Arduino, então eu coloquei o "maintain" executando ali, de forma a renovar o IP automaticamente caso necessário (via DHCP como descrito na própria funcionalidade do "maintain"). Mas talvez essa não tenha sido uma boa ideia.
Então minhas sugestões são:
Opção 1: usar a função "maintain" da LIB, mas com uma temporização própria, pois atualmente ele está sendo executado logo após a conclusão de cada requisição ao Host . E também nunca executar antes de um certo tempo depois da conclusão da comunicação com o Host.
Opção 2: usar a função "linkStatus" da LIB para detectar que ocorreu uma desconexão. E isto também de forma temporizada, ou seja da mesma forma que na "Opção 1". Mas o "linkStatus" não tem o problema do "maintain". E quando o "linkStatus" indicar uma desconexão, então usamos o "Ethernet.begin" para reconectar. Neste caso, é muito importante acompanhar o histórico das mensagens de RAM "free", para constatarmos que após uma reconexão, a LIB "UIP" não está alocando mais Memória, ou seja, não está gradativamente diminuindo o RAM "free" (se for diminuindo, isto pode levar ao "crash" do Sistema).
Eu voto pela "Opção 2". É mais radical, mas me parece mais sensata neste momento. E na "Opção 1", nada garante que o "maintain" não vá causar problemas, mesmo que mais esparsos.
Aguardo sua opinião.
(não se preocupe, pois é tranquilo de fazer estas implementações no código)
Abrçs,
Elcids…
Adicionado por Elcids Chagas ao 1:46 em 2 outubro 2020
s botoes alguem sabe se isso daria certo? ou daria sobrecarga ou curto?
pois pretendo usar esse codigo para os macros...
//projeto Macro mouse generico int botDIR=13;//entrada botao direito int botdir=12;//saida transistor direita int botESQ=11;//entrdada botao esquerdo int botesq=10;//saida transistor esquerda int botCTR=9;//entrada botao central(roda do mouse) int botctr=8;//saida botaocentral(roda do mouse) int bot1LTR=7;//entrada 1 botao lateral int botltr1=6;//saida de transistor botao lateral int bot2LTR=5;//entrada 2 botao lateral int botltr2=4;//saida botao lateral int botMODE=3;//entrada botao Mode gamming (CPI) int mode=0;
#define t_500 delay(500); //ativa e desativa os botoes #define ligEsq digitalWrite(botesq, HIGH);//liga e deslia esq #define desEsq digitalWrite(botesq, LOW); #define ligDir digitalWrite(botdir, HIGH);//liga e desliga direito #define desDir digitalWrite(botdir, LOW); #define ligLtr1 digitalWrite(botltr1, HIGH);//liga e desliga o lateral 1 #define desLtr1 digitalWrite(botltr1, LOW); #define ligLtr2 digitalWrite(botltr2, HIGH);//liga e desliga o lateral 2 #define desLtr2 digitalWrite(botltr2, LOW); #define ligCtr digitalWrite(botctr, HIGH);//liga e desliga o central #define desCtr digitalWrite(botctr, LOW); //Principais Skills do Macro---------------------------------------------------------------------------------------------------------------------------------------------- #define Pressed_Dir int botDIR1 = digitalRead(botDIR); if(botDIR1 == LOW){ligDir;}else{desDir;} #define Pressed_Esq int botESQ1 = digitalRead(botESQ); if(botESQ1 == LOW){ligEsq;}else{desEsq;} #define Pressed_Esq_3kill int botESQ1 = digitalRead(botESQ); if(botESQ1 == LOW){int conte=0; if(conte <3){ ligEsq; t_500; desEsq; t_500; conte++;}}else{desEsq;} #define Pressed_Esq_Scope int botESQ1 = digitalRead(botESQ); if(botESQ1 == LOW){ligDir; t_500; ligEsq; t_500; desEsq; desDir;} #define Pressed_1Ltr int botLTR1 = digitalRead(bot1LTR); if(botLTR1 == LOW){ligLtr1; }else{desLtr1;} #define Pressed_2Ltr int botLTR2 = digitalRead(bot2LTR); if(botLTR2 == LOW){ligLtr2;}else{desLtr2;} #define Pressed_Ctr int botCTR1 = digitalRead(botCTR); if(botCTR1 == LOW){ligCtr; }else{desCtr;} #define Pressed_Mode int botMODE1 = digitalRead(botMODE); if(botMODE1 == LOW){mode++; t_500;}if(mode == 5){mode=0;}//seleciona o n max de perfis que atualmente é 5 //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
void setup(){ //PULLUP PERMITE LIGAR UM BOTAO AO TERRA DIRETAMENTE pinMode(botDIR,INPUT_PULLUP);//Entrada direita pinMode(botdir,OUTPUT);//saida direita pinMode(botESQ,INPUT_PULLUP);//Entrada esquerda pinMode(botesq,OUTPUT);//saida esquerda pinMode(botCTR,INPUT_PULLUP); //Entrada do botao da roda do mouse pinMode(botctr,OUTPUT);//saida do botao da roda do mouse pinMode(bot1LTR,INPUT_PULLUP);//Entrada do botao lateral 1 pinMode(botltr1,OUTPUT);//saida botao lateral 1 pinMode(bot2LTR,INPUT_PULLUP);// Entrada do botao lateral 2 pinMode(botltr2,OUTPUT);//saida botao lateral 2 pinMode(botMODE,INPUT_PULLUP);// Entrada do botao CPI do mouse }//fim do void setup
void loop(){ Pressed_Mode; //perfil normal if(mode == 0){ Pressed_Dir; Pressed_Esq; Pressed_1Ltr; Pressed_2Ltr; Pressed_Ctr; } //fim do perfil normal //perfil sniper if(mode == 1){ Pressed_Esq_Scope; Pressed_Dir; Pressed_1Ltr; Pressed_2Ltr; Pressed_Ctr; } //fim do perfil sniper //perfil 3balas por vez if(mode == 2){ Pressed_Dir; Pressed_Esq_3kill; Pressed_1Ltr; Pressed_2Ltr; Pressed_Ctr; } //fim do perfil 3balas }//fim do void loop
…
o motor de passo tem que dar uma volta completa, e conforme o andar vai mudando deverá aparecer no LCD o andar que está.
Eu comecei a fazer o programa, cada volta do motor de passo é equivalente 200 no registrador. Fiz com que a cada tecla apertada (1, 2, 3 e 4) o motor gire correspondente com a tecla. O LCD não está funcionando, no programa há outras teclas habilitadas, mas não usarei elas.
A minha dificuldade no momento é fazer com que se caso a tecla 1 for apertada e após o motor ter girado uma volta completa vier uma pessoa e apertar a tecla 2 o motor deverá girar mais uma volta completa, totalizando duas voltas e parando no andar 2. Tenho em mente em colocar algo relacionado :
JB BIT 2,(vá para uma outra instrução, que no caso no momento não é necessário saber) ;se a tecla 2 for apertada=vai para a instrução abaixo)
ANDAR1: MOV R4,#200RET0: RL A ;movendo para direita (motor andando) MOV P1,A CALL DELAY DJNZ R4,RET0 JMP STOP RET
Também preciso fazer com que o motor volte dependendo da tecla pressionada e andar atual. Pensei em fazer igual ao de cima, porém com RR A no lugar do RL A.
Eu tentei fazer dessa maneira que descrevi, porém não obtive resultado. Alguém pode me ajudar?
Segue o programa que fiz até o momento:
;#########################################################################################; Leitura de Teclado;#########################################################################################
LCD XDATA 0FF40HLINHA XDATA 0FF60HCOLUNA XDATA 0FF50HTLIDA DATA 020HBIT0 BIT 00HBIT1 BIT 01HBIT2 BIT 02HBIT3 BIT 03HBIT4 BIT 04HBIT5 BIT 05HBIT6 BIT 06HBIT7 BIT 07HK7 EQU 'A'K8 EQU 'B'K9 EQU 'C'K4 EQU 'F'K2 EQU 'D'K3 EQU 'E'K12 EQU '7'K13 EQU '8'K14 EQU '9'K17 EQU '4'K18 EQU '5'K19 EQU '6'K22 EQU '1'K23 EQU '2'K24 EQU '3'K27 EQU '#'K28 EQU '0'K29 EQU '.'
;#################################################################################; PROGRAMA PRINCIPAL;#################################################################################
MAIN: MOV SP,#25H MOV TMOD,#10H MOV TCON,#0 CLR EA
INICIO: CALL INILCD MOV A, #80H CALL CMLCD CALL LETECL CJNE A,#255, ESCREVE LJMP INICIO
ESCREVE: CALL WRLCD CALL ESPETEC LJMP INICIO ;#################################################################################; ROTINA DE LEITURA DE TECLADO;#################################################################################
LETECL: MOV A,#11111110B MOV DPTR,#LINHA MOVX @DPTR,A MOV DPTR,#COLUNA MOVX A,@DPTR MOV TLIDA,A JB BIT3,NOK2 MOV A,#K2 RET
NOK2: JB BIT2,NOK3 MOV A,#K3 RET
NOK3: JB BIT1,NOK4 MOV A,#K4 RET
NOK4: MOV A,#11111101B MOV DPTR,#LINHA MOVX @DPTR,A MOV DPTR,#COLUNA MOVX A,@DPTR MOV TLIDA,A JB BIT3,NOK7 MOV A,#K7 RET
NOK7: JB BIT2,NOK8 MOV A,#K8 RET
NOK8: JB BIT2,NOK9 MOV A,#K9 RET
NOK9: MOV A,#11111011B MOV DPTR,#LINHA MOVX @DPTR,A MOV DPTR,#COLUNA MOVX A,@DPTR MOV TLIDA,A JB BIT3,NOK12 MOV A,#K12 RET
NOK12: JB BIT2,NOK13 MOV A,#K13 RET
NOK13: JB BIT1,NOK14 MOV A,#K14 RET
NOK14: MOV A,#11110111B MOV DPTR,#LINHA MOVX @DPTR,A MOV DPTR,#COLUNA MOVX A,@DPTR MOV TLIDA,A JB BIT3,NOK17 ;se clicar na tecla 4= o motor dá 4 voltas MOV A,#K17;########################################################################; ANDAR 4;########################################################################ANDAR4: MOV R4,#200RET6: RL A ;movendo para direita (motor andando) MOV P1,A CALL DELAY DJNZ R4,RET6
ANDAR4A: MOV R4,#200RET7: RL A ;movendo para direita (motor andando) MOV P1,A CALL DELAY DJNZ R4,RET7 ANDAR4AN: MOV R4,#200RET8: RL A ;movendo para direita (motor andando) MOV P1,A CALL DELAY DJNZ R4,RET8 ANDAR4AND: MOV R4,#200RET9: RL A ;movendo para direita (motor andando) MOV P1,A CALL DELAY DJNZ R4,RET9 JMP STOP RET
;#################################################################################
NOK17: JB BIT2,NOK18 MOV A,#K18 RET
NOK18: JB BIT1,NOK19 MOV A,#K19 RET
NOK19: MOV A,#11101111B MOV DPTR,#LINHA MOVX @DPTR,A MOV DPTR,#COLUNA MOVX A,@DPTR MOV TLIDA,A JB BIT3,NOK22 ;se clicar na tecla 1= o motor dá uma volta MOV A,#K22;###############################################################################; ANDAR 1;###############################################################################
ANDAR1: MOV R4,#200RET0: RL A ;movendo para direita (motor andando) MOV P1,A CALL DELAY DJNZ R4,RET0 JMP STOP RET
;################################################################################; ANDAR 2;################################################################################NOK22: JB BIT2,NOK23 ;se clicar na tecla 2= o motor dá 2 voltas MOV A,#K23ANDAR2: MOV R4,#200RET1: RL A ;movendo para direita (motor andando) MOV P1,A CALL DELAY DJNZ R4,RET1
ANDAR2A: MOV R5,#200RET2: RL A ;movendo para direita (motor andando) MOV P1,A CALL DELAY DJNZ R5,RET2 JMP STOP RET;###############################################################################NOK23: JB BIT1,NOK24 ;se clicar na tecla 3= o motor dá 3 voltas MOV A,#K24;###############################################################################; ANDAR 3;###############################################################################ANDAR3: MOV R4,#200RET3: RL A ;movendo para direita (motor andando) MOV P1,A CALL DELAY DJNZ R4,RET3
ANDAR3A: MOV R4,#200RET4: RL A ;movendo para direita (motor andando) MOV P1,A CALL DELAY DJNZ R4,RET4 ANDAR3AN: MOV R4,#200RET5: RL A ;movendo para direita (motor andando) MOV P1,A CALL DELAY DJNZ R4,RET5 JMP STOP RET
;#################################################################################
NOK24: MOV A,11011111B MOV DPTR,#LINHA MOVX @DPTR,A MOV DPTR,#COLUNA MOVX A,@DPTR MOV TLIDA,A JB BIT3,NOK27 MOV A,#K27 RET
NOK27: JB BIT2,NOK28 MOV A,#K28 RET
NOK28: JB BIT1,NOK29 MOV A,#K29 RET
NOK29: MOV A,#255 RET ;#################################################################################; ROTINA DO INICIALIZAÇÃO DO LCD;#################################################################################
INILCD: MOV A,#039H CALL CMLCD MOV A,#006H CALL CMLCD MOV A,#001H CALL CMLCD MOV A,#00EH CALL CMLCD RET
;#################################################################################; ROTINA DE ESCRITA DE UM COMANDO PARA O DISPLAY LCD;################################################################################CMLCD: MOV DPTR,#LCD MOVX @DPTR,A MOV R6,#250CMLCDT: NOP NOP NOP NOP DJNZ R6,CMLCDT RET;#################################################################################; ROTINA DE ESCRITA DE UM CARACTER NO DISPLAY;#################################################################################WRLCD: MOV R4,DPL MOV R5,DPH MOV DPTR,#LCD INC DPTR MOVX @DPTR,A MOV R6,#200 DJNZ R6,$ MOV DPL,R4 MOV DPH,R5 RET;#################################################################################; ROTINA DE ESPERA DE 30MS E SOLTAR TECLA;#################################################################################
ESPETEC: MOV R5,#15INI: MOV TH1,#HIGH(65535-40000) MOV TL1,#LOW(65535-40000) SETB TR1 JNB TF1,$ CLR TF1 DJNZ R5,INI CLR TR1
ESPSOL: CALL LETECL CJNE A,#255,ESPSOL RET
DELAY: MOV R7,#09FHL1: MOV R6,#04FHL2: DJNZ R6,L2 DJNZ R7,L1 RET STOP: MOV A,#0 MOV R4,#0 JMP $ RET
END
…
e "atmega328lib.inc"; diretiva de inclusão de arquivo de biblioteca com rotinas pré -programadas
setup: ; nome da linha (rótulo ou label)sbi ddrd, 2 ; D2->saida lógica (pino2)sbi ddrd, 3 ; D3->saida lógica (pino3)sbi ddrd, 4 ; D4->saida lógica (pino4)sbi ddrd, 5 ; D5->saida lógica (pino5)sbi ddrb, 0 ; B0->saida lógica (pino8)sbi ddrb, 1 ; B1->saida lógica (pino9)sbi ddrb, 2 ; B2->saida lógica (pino10)sbi ddrb, 3 ; B3->saida lógica (pino11)call defesa; chama rotina de defesa (servo em 0 graus)cpi w, '0' ; compara o valor do reg trabalho w (r16) com o caracter zero brne pc + 2 ;call parado ; chama rotina de robo paradocpi w, '1' ; compara o valor do reg trabalho w (r16) com o caracter zero brne pc + 2 ;call avanco ; chama rotina de avanco do robo cpi w, '5' ; compara o valor do reg trabalho w (r16) com o caracter zero brne pc + 2 ;call reverso ; chama rotina de reversao do robo cpi w, '3' ; compara o valor do reg trabalho w (r16) com o caracter zero brne pc + 2 ;call direita ; chama rotina de de girar o robo para direitacpi w, '7' ; compara o valor do reg trabalho w (r16) com o caracter zero brne pc + 2 ;call esquerda ; chama rotina de de girar o robo para esquerdacpi w, 'A' ; compara o valor do reg trabalho w (r16) com o caracter zero brne pc + 2 ;call ataque ; chama rotina de ataque (servomotor em 90 graus)cpi w, 'B' ; compara o valor do reg trabalho w (r16) com o caracter zero brne pc + 2 ;call defesa ; chama rotina de defesa (servomotor em 0)
parado: ; nome da rotina; motores direitasbi portd, 2 ; D2 (pino2) em Hsbi portd, 3 ; D3 (pino3) em Hsbi portd, 5 ; D5 (pino5) em Hsbi portd, 4 ; D4 (pino4) em H; motores esquerdasbi portb, 0 ; B0 (pino8) em Hsbi portb, 1 ; B1 (pino9) em Hsbi portb, 3 ; B3 (pino11) em Hsbi portb, 2 ; B2 (pino10) em H
avanco: ; nome da rotina; motores direitacbi portd, 2 ; D2 (pino2) em Lsbi portd, 3 ; D3 (pino3) em Hsbi portd, 5 ; D5 (pino5) em Hcbi portd, 4 ; D4 (pino4) em L; motores esquerdacbi portb, 0 ; B0 (pino8) em Lsbi portb, 1 ; B1 (pino9) em Hsbi portb, 3 ; B3 (pino11) em Hcbi portb, 2 ; B2 (pino10) em L
reverso: ; nome da rotina; motores direitasbi portd, 2 ; D2 (pino2) em Hcbi portd, 3 ; D3 (pino3) em Lcbi portd, 5 ; D5 (pino5) em Lsbi portd, 4 ; D4 (pino4) em H; motores esquerdasbi portb, 0 ; B0 (pino8) em Hcbi portb, 1 ; B1 (pino9) em Lcbi portb, 3 ; B3 (pino11) em Lsbi portb, 2 ; B2 (pino10) em H
direita: ; nome da rotina; motores esquerdacbi portb, 0 ; B0 (pino8) em Lsbi portb, 1 ; B1 (pino9) em Hsbi portb, 3 ; B3 (pino11) em Hcbi portb, 2 ; B2 (pino10) em L; motores direitasbi portd, 2 ; D2 (pino2) em Hcbi portd, 3 ; D3 (pino3) em Lcbi portd, 5 ; D5 (pino5) em Lsbi portd, 4 ; D4 (pino4) em Hret ; retorna da chamda da rotina
esquerda: ; nome da rotina; motores direitacbi portd, 2 ; D2 (pino2) em Lsbi portd, 3 ; D3 (pino3) em Hsbi portd, 5 ; D5 (pino5) em Hcbi portd, 4 ; D4 (pino4) em L; motores esquerdasbi portb, 0 ; B0 (pino8) em Hcbi portb, 1 ; B1 (pino9) em Lcbi portb, 3 ; B3 (pino11) em Lsbi portb, 2 ; B2 (pino10) em Hret ; retorna da chamada da rotina
defesa: ; nome da rotinasbi portb, 4 ; pulso em Hldi w, 1 ; carrega o registra w com o valor 1call delay_ms ; chama rotina de pausa em ms com o valor de wcbi portb, 4 ; pulso em Lldi w, 19 ; carrega o registra w com o valor 19call delay_ms ; chama rotina de pausa em ms com o valor de wsbi portb, 4 ; pulso em Hldi w, 1 ; carrega o registra w com o valor 1call delay_ms ; chama rotina de pausa em ms com o valor de wcbi portb, 4 ; pulso em Lldi w, 19 ; carrega o registra w com o valor 19call delay_ms ; chama rotina de pausa em ms com o valor de wret ; retorna da chamada da rotina
ataque: ; nome da rotinasbi portb, 4 ; pulso em Hldi w, 1 ; carrega o registra w com o valor 1call delay_ms ; chama rotina de pausa em ms com o valor de wldi w, 200 ; carrega o registra w com o valor 200call delay_us ; chama rotina de pausa em ms com o valor de wldi w, 200 ; carrega o registra w com o valor 200call delay_us ; chama rotina de pausa em ms com o valor de wldi w, 100 ; carrega o registra w com o valor 100call delay_us ; chama rotina de pausa em ms com o valor de wcbi portb, 4 ; pulso em Lldi w, 18 ; carrega o registra w com o valor 18call delay_ms ; chama rotina de pausa em ms com o valor de wldi w, 200 ; carrega o registra w com o valor 200call delay_us ; chama rotina de pausa em ms com o valor de wldi w, 200 ; carrega o registra w com o valor 200call delay_us ; chama rotina de pausa em ms com o valor de wldi w, 100 ; carrega o registra w com o valor 100call delay_us ; chama rotina de pausa em ms com o valor de wsbi portb, 4 ; pulso em Hldi w, 1 ; carrega o registra w com o valor 1call delay_ms ; chama rotina de pausa em ms com o valor de wldi w, 200 ; carrega o registra w com o valor 200call delay_us ; chama rotina de pausa em ms com o valor de wldi w, 200 ; carrega o registra w com o valor 200call delay_us ; chama rotina de pausa em ms com o valor de wldi w, 100 ; carrega o registra w com o valor 100call delay_us ; chama rotina de pausa em ms com o valor de wcbi portb, 4 ; pulso em Lldi w, 18 ; carrega o registra w com o valor 18call delay_ms ; chama rotina de pausa em ms com o valor de wldi w, 200 ; carrega o registra w com o valor 200call delay_us ; chama rotina de pausa em ms com o valor de wldi w, 200 ; carrega o registra w com o valor 200call delay_us ; chama rotina de pausa em ms com o valor de wldi w, 100 ; carrega o registra w com o valor 100call delay_us ; chama rotina de pausa em ms com o valor de wret ; retorna da chamada da rotina…
Veja: no UNO...”
Veja bem, utilizo o esp32 em outra placa para simular um pwm através do 595. Diferente do código atual, não utilizo o “digitalWrite”, mas sim os registradores. Não possui nenhum delay, funciona perfeitamente. (ao menos na bancada, na placa ainda não testei).
2) Sobre o Feder, considerando apenas uma chave de on/off, isso seria tão errado assim?
É apenas a título de curiosidade, pois apenas o RC economiza espaço e componente.
3) Sobre AmpOp,
nunca usei/testei. É mais uma nova situação para ser estudada. Mas sinto que vou gastar longas e longas horas com este carinha aqui. Confere?
4) Sobre o hc594
Não localizei o componente no formato dip. No aliexpress, apenas SMD. Eu tenho uma certa resistência com smd, pois AINDA acho o formato muito pequeno para mim. Sei que SMD é o único caminho, a diferença no tamanho final da pcb é ENOOOOOORME. Num “remake” de um projeto que tenho, chegou a quase 1/4 ou 1/3 do tamanho total. Entretanto, isso implicaria em adquirir novos componentes, novas ferramentas, mais tempo para praticar, e nisso vai mais dinheiro junto.
O drama disso tudo, é que desde que comecei a estudar um pouco sobre eletrônica, existe um loop infinito de: “precisa de componente -> componente encontrado -> novo problema/recurso -> novo componente que faz tudo que o anterior só que mais rápido, melhor e consome menos energia -> repete o loop”
Cheguei num ponto que, incomodado com o loop, bati o pé no chão e disse: “Não vou comprar mais nada até concluir alguma coisa” e colocar pra funcionar. As placas que fiz, estão com este pensamento.
A chance de migrar pro smd futuramente é de 99,99%, mas só depois de concluir essa primeira etapa.
E essa decisão veio pois caiu a ficha que entrei no mesmo loop "da perfeição" de quando eu escrevia códigos para tentar criar jogos, mas nunca cheguei a terminar nenhum, pois não defini um final e ficava sempre polindo. Depois que caiu a ficha, produzi um outro bem simples para ajudar o pessoal que tinha dificuldade para digitar: https://digitarrapido.wordpress.com/
Atenção: Caso tenham curiosidade e resolvam baixar, mas durante a execução, ou instalação, ele alegar a existência de algum tipo de vírus, pode excluir sem medo. É um falso positivo que não interfere no funcionamento do jogo. Este ".exe" foi um arquivo criado em delphi para compactar um conjunto de blocos de notas com os resultados da partida e depois enviar para um e-mail específico. Despois eu atualizava manualmente os ranks. (foi uma péssima ideia, pois em pouco tempo o google identificou até chineses tentando entrar na minha conta. kkkk)
Star Citizen é um exemplo do loop da perfeição, mas diferente de mim, o pessoal já recebeu mais de 250 milhões de DOLARES em doação, para a conclusão do jogo, além de arrecadar quase 5 milhões por mês, ainda hoje. (E TA EM DESENVOLVIMENTO!). Nesse caso, contrata 1000 pessoas e coloca todo mundo para trabalhar.
obs- um outro bom CI seria o tpic6b595 (ou algum dos seus familiares).
5) “ sobre o layout.”
Eu dei muita risada ao ler “quase dá pra dizer que não há padrão no seu layout” kkkkk, e eu tinha me esforçado tanto para ficar bonitinho. Mas faz parte, é a primeira tentativa, tenho muito o que melhorar ainda.
Sobre as trilhas em si, poucas foram realmente feitas por mim. As que fiz são fáceis de serem identificadas, pois possuem uma curva bem bonitinha, sem ângulos. Dentre elas, as que ligam 3 terminais do 4051b a 3 pads no canto central esquerdo, e outra do 4051b que vai até R20.
Todas as demais foram feitas pelo roteamento automático do proteus. Devido a meu conhecimento, ainda, pequeno, este era o melhor recurso que eu tinha. Em todo caso, é muito bom saber sobre estas questões e saber que existem programas específicos para este fim (quando li seu comentário, comecei a achar que era tudo manual), pois, futuramente, a quantidade de imperfeições tenderá a ser um pouco menor.
6) “Veja no "Bottom" alguns pontos que salientei:”
Realmente, são curvas totalmente estranhas e sem sentido.
Sobre as áreas do gnd, eu tinha visto que era sempre bom ter grandes áreas com gnd na placa, pois isso evitava o ground loop e outros problemas. Por isso, defini a largura das trilhas e no final coloquei um “chapeado” de gnd em todas as áreas disponíveis da parte inferior.
7) Geralmente se usa "U" para essa referência.
Sim, vi em algumas placas que desmontei que isso era muito comum, imaginei que fosse um padrão, toda via também achei que seria mais fácil, para mim (tendo em vista que é a primeira experiência), na hora de soldar os componentes, se eles já tivessem alguma referência.
Eu cheguei a pensar em colocar os componentes assim: “R20 – 180k”, “U3 74hc595_A” mas esse acréscimo começou a deixar o visual muito poluído e bagunçado.
8) “c pode interromper a trilha que liga o "DOUT" do HC165 ao ESP, e interconectá-la conforme a figura a seguir:”
Fiquei surpreso com a simplicidade da solução e como eu não tinha pensado nisso antes.
Obs- Sou da bahia, aqui está chovendo muito. Boa humidade.
9) “ Se o "A" funcionou corretamente, e o "B" não, então é...”
Bem, lendo isso resolvi fazer o mesmo teste que fiz com o pino 14 e 9.
74hc595_A pino 14 ao 74hc595_B pino 9
595_A pino 11 ao 595_B pino 11
595_A pino 12 ao 595_B pino 12.
O ci esta no 595_C, os outros, obviamente, vazios.
Resultado: o 595C respondeu corretamente.
Em seguida removi o jumper entre os pinos 12, E continuo funcionando. Em seguida removi o jumper entre os pinos 11, e parou de funcionar.
O pino 11 é o pino de clock.
Depois disso, feliz em ter descoberto o problema, mas lembrando que já tive problema com os leds, resolvi voltar ao esquema só para tirar uma duvida, e ter certeza que não era o mesmo erro. Ao chegar lá, descubro que coloquei tags diferentes.
Aparentemente, os problemas estão descobertos. Amanhã (02 de setembro), irei ligar os terminais com um pedaço de fio, assim como os que estão conectados aos leds, então postarei os resultados.
10) Aproveitando que já chegamos até aqui... “E obrigatoriamente deve ser um Capacitor do tipo Cerâmico “
Pq obrigatoriamente o cerâmico? Existiria problema em adicionar um capacitor eletrolítico de valor maior? Exemplo: 100, 470 ou 1000uf? Apenas por curiosidade.…
Adicionado por tiago merces ao 21:02 em 1 setembro 2021