finalizado implementacao i2c robusta

This commit is contained in:
Diego Freitas 2025-04-25 17:28:38 -03:00
parent a7cec85038
commit f82131569d
35 changed files with 611 additions and 334 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -1219,14 +1219,14 @@ namespace AgroBase.Forms.IHM
bool PzmConectado = SerialService.DispositivosMapeados.Any(x => x.Dispositivo == Enums.T_Code.Pzm); bool PzmConectado = SerialService.DispositivosMapeados.Any(x => x.Dispositivo == Enums.T_Code.Pzm);
idx = PreencheDadosLinha(grid, Testes, idx, PzmConectado ? 1 : 0); idx = PreencheDadosLinha(grid, Testes, idx, PzmConectado ? 1 : 0);
var S36V = ((FirmwareSensorCorrente)Modulo_Sen.Sensores.FirstOrDefault(x => x.ID == "AB36V").Leitura); var S36V = Variaveis.OperacaoEmAndamento.Sensoriamento.Bateria;
bool S36VInicializado = S36V?.Iniciado ?? false; bool S36VInicializado = S36V.Iniciado;
idx = PreencheDadosLinha(grid, Testes, idx, S36VInicializado ? 1 : 0); idx = PreencheDadosLinha(grid, Testes, idx, S36VInicializado ? 1 : 0);
double Tensao = S36VInicializado ? S36V.BusVoltage : -1; double Tensao = S36VInicializado ? S36V.TensaoInstantanea : -1;
idx = PreencheDadosLinha(grid, Testes, idx, Tensao); idx = PreencheDadosLinha(grid, Testes, idx, Tensao);
double Corrente = S36VInicializado ? S36V.Current : -1; double Corrente = S36VInicializado ? S36V.CorrenteInstantanea : -1;
idx = PreencheDadosLinha(grid, Testes, idx, Corrente); idx = PreencheDadosLinha(grid, Testes, idx, Corrente);
bool SenConectado = SerialService.DispositivosMapeados.Any(x => x.Dispositivo == T_Code.Sen); bool SenConectado = SerialService.DispositivosMapeados.Any(x => x.Dispositivo == T_Code.Sen);
@ -1266,13 +1266,13 @@ namespace AgroBase.Forms.IHM
bool GpsInicializado = GPSService.Iniciado; bool GpsInicializado = GPSService.Iniciado;
idx = PreencheDadosLinha(grid, Testes, idx, GpsInicializado ? 1 : 0); idx = PreencheDadosLinha(grid, Testes, idx, GpsInicializado ? 1 : 0);
double Precisao = GpsInicializado ? (int)GPSService.UltimaLeitura.QualidadeFix : -1; double Precisao = GpsInicializado ? (int)Variaveis.OperacaoEmAndamento.Sensoriamento.Gps.QualidadeFix : -1;
idx = PreencheDadosLinha(grid, Testes, idx, Precisao); idx = PreencheDadosLinha(grid, Testes, idx, Precisao);
double Satelites = GpsInicializado ? GPSService.UltimaLeitura.NumeroSatelites : -1; double Satelites = GpsInicializado ? Variaveis.OperacaoEmAndamento.Sensoriamento.Gps.NumeroSatelites : -1;
idx = PreencheDadosLinha(grid, Testes, idx, Satelites); idx = PreencheDadosLinha(grid, Testes, idx, Satelites);
double OrientacaoGPS = GpsInicializado ? GPSService.UltimaLeitura.CursoVerdadeiro : -1; double OrientacaoGPS = GpsInicializado ? Variaveis.OperacaoEmAndamento.Sensoriamento.Gps.OrientacaoReal : -1;
idx = PreencheDadosLinha(grid, Testes, idx, OrientacaoGPS); idx = PreencheDadosLinha(grid, Testes, idx, OrientacaoGPS);
bool A05Conectado = SerialService.DispositivosMapeados.Any(x => x.Dispositivo == Enums.T_Code.A05); bool A05Conectado = SerialService.DispositivosMapeados.Any(x => x.Dispositivo == Enums.T_Code.A05);

View File

@ -387,10 +387,11 @@ namespace AgroBase.Forms.Operacoes
private void pnlAnguloMagnetometro_Paint(object sender, PaintEventArgs e) private void pnlAnguloMagnetometro_Paint(object sender, PaintEventArgs e)
{ {
var imu = Variaveis.OperacaoEmAndamento.Sensoriamento.IMU;
try try
{ {
double angulo = Variaveis.OperacaoEmAndamento.DispSen?.Dados?.DadosLeitura?.SensoresIMU?.FirstOrDefault()?.Yaw ?? -1; double angulo = imu.Rotacao;
double anguloCorrigido = Variaveis.OperacaoEmAndamento.DispSen?.Dados?.DadosLeitura?.SensoresIMU?.FirstOrDefault()?.YawFixed ?? -1; double anguloCorrigido = imu.RotacaoCorrigida;
FuncoesGlobais.DesenharInclinacao((Panel)sender, e, (float)angulo, -270, (float)anguloCorrigido); FuncoesGlobais.DesenharInclinacao((Panel)sender, e, (float)angulo, -270, (float)anguloCorrigido);
} }
catch { } catch { }
@ -443,6 +444,10 @@ namespace AgroBase.Forms.Operacoes
gridDados.Rows.Add("Temperatura", "", ""); gridDados.Rows.Add("Temperatura", "", "");
gridDados.Rows.Add("Pressao", "", ""); gridDados.Rows.Add("Pressao", "", "");
gridDados.Rows.Add("Altitude", "", ""); gridDados.Rows.Add("Altitude", "", "");
gridDados.Rows.Add("Temperatura ET", "", "");
gridDados.Rows.Add("Temperatura EF", "", "");
gridDados.Rows.Add("Temperatura DT", "", "");
gridDados.Rows.Add("Temperatura DF", "", "");
AtualizarInformacoesGerais(); AtualizarInformacoesGerais();
} }
@ -457,7 +462,6 @@ namespace AgroBase.Forms.Operacoes
var AB19V = _SensoresCorrente.FirstOrDefault(x => x.ID == "AB19V"); var AB19V = _SensoresCorrente.FirstOrDefault(x => x.ID == "AB19V");
var AB24V = _SensoresCorrente.FirstOrDefault(x => x.ID == "AB24V"); var AB24V = _SensoresCorrente.FirstOrDefault(x => x.ID == "AB24V");
var _Sensoriamento = Variaveis.OperacaoEmAndamento.Sensoriamento; var _Sensoriamento = Variaveis.OperacaoEmAndamento.Sensoriamento;
var _SensorIMU = Variaveis.OperacaoEmAndamento.DispSen.Dados.DadosLeitura.SensoresIMU.FirstOrDefault();
gridDados.Rows[0].Cells[1].Value = _Sensoriamento.TempoDecorrido.ToString("HH:mm:ss"); gridDados.Rows[0].Cells[1].Value = _Sensoriamento.TempoDecorrido.ToString("HH:mm:ss");
gridDados.Rows[1].Cells[1].Value = _Sensoriamento.Movimentacao.TempoMovimento.ToString("HH:mm:ss"); gridDados.Rows[1].Cells[1].Value = _Sensoriamento.Movimentacao.TempoMovimento.ToString("HH:mm:ss");
@ -487,12 +491,12 @@ namespace AgroBase.Forms.Operacoes
gridDados.Rows[25].Cells[1].Value = _Sensoriamento.Atuador.VazaoMedia.ToString("0.00"); gridDados.Rows[25].Cells[1].Value = _Sensoriamento.Atuador.VazaoMedia.ToString("0.00");
gridDados.Rows[26].Cells[1].Value = _Sensoriamento.Atuador.VolumeVazaoMl.ToString("0.00"); gridDados.Rows[26].Cells[1].Value = _Sensoriamento.Atuador.VolumeVazaoMl.ToString("0.00");
gridDados.Rows[27].Cells[1].Value = ""; gridDados.Rows[27].Cells[1].Value = "";
gridDados.Rows[28].Cells[1].Value = (_SensorIMU?.Roll ?? 0).ToString("0.00"); gridDados.Rows[28].Cells[1].Value = (_Sensoriamento.IMU.InclinacaoLateral).ToString("0.00");
gridDados.Rows[29].Cells[1].Value = (_SensorIMU?.Pitch ?? 0).ToString("0.00"); gridDados.Rows[29].Cells[1].Value = (_Sensoriamento.IMU.InclinacaoFrontal).ToString("0.00");
gridDados.Rows[30].Cells[1].Value = (_SensorIMU?.Yaw ?? 0).ToString("0.00"); gridDados.Rows[30].Cells[1].Value = (_Sensoriamento.IMU.Rotacao).ToString("0.00");
gridDados.Rows[31].Cells[1].Value = (_SensorIMU?.Temperatura ?? 0).ToString("0.00"); gridDados.Rows[31].Cells[1].Value = (_Sensoriamento.IMU.Temperatura).ToString("0.00");
gridDados.Rows[32].Cells[1].Value = (_SensorIMU?.Pressao ?? 0).ToString("0.00"); gridDados.Rows[32].Cells[1].Value = (_Sensoriamento.IMU.Pressao).ToString("0.00");
gridDados.Rows[33].Cells[1].Value = (_SensorIMU?.Altitude ?? 0).ToString("0.00"); gridDados.Rows[33].Cells[1].Value = (_Sensoriamento.IMU.Altitude).ToString("0.00");
} }
#endregion #endregion

View File

@ -69,7 +69,7 @@ namespace AgroBase.Forms
AtualizarDadosSensorCorrente("AB36V", lblB36V); AtualizarDadosSensorCorrente("AB36V", lblB36V);
} }
lblMagnetometro.ForeColor = (Variaveis.OperacaoEmAndamento.DispSen?.Dados?.DadosLeitura?.SensoresIMU?.DefaultIfEmpty()?.FirstOrDefault()?.Iniciado ?? false) ? Color.Green : Color.Red; lblMagnetometro.ForeColor = Variaveis.OperacaoEmAndamento.Sensoriamento.IMU.Iniciado ? Color.Green : Color.Red;
var Gps = Variaveis.OperacaoEmAndamento.Sensoriamento.Gps; var Gps = Variaveis.OperacaoEmAndamento.Sensoriamento.Gps;
lblGPS.ForeColor = Gps.Inicializado ? Color.Green : Color.Red; lblGPS.ForeColor = Gps.Inicializado ? Color.Green : Color.Red;
@ -102,6 +102,8 @@ namespace AgroBase.Forms
foreach (var Modulo in DispMvd.Dados.Modulos) foreach (var Modulo in DispMvd.Dados.Modulos)
{ {
var sTMP = Variaveis.OperacaoEmAndamento.DispSen?.Dados?.DadosLeitura?.SensoresTemperatura?.FirstOrDefault(x => x.ID.Contains(Modulo.Modulo_ID));
Label lblTitulo = pnlFundo.Controls.OfType<Label>().FirstOrDefault(ctrl => ctrl.Name == "lblM_" + Modulo.Modulo_ID); Label lblTitulo = pnlFundo.Controls.OfType<Label>().FirstOrDefault(ctrl => ctrl.Name == "lblM_" + Modulo.Modulo_ID);
lblTitulo.ForeColor = Modulo.MovMotor.Comandar ? Modulo.MovMotor.Inicializado ? Color.Green : Color.Red : Color.Black; lblTitulo.ForeColor = Modulo.MovMotor.Comandar ? Modulo.MovMotor.Inicializado ? Color.Green : Color.Red : Color.Black;
lblTitulo.Text = lblTitulo.Text.Split(' ')[0] + " (" + Modulo.Modulo_ID + ") - Alm: " + Modulo.MovMotor.CodigoAlarme; lblTitulo.Text = lblTitulo.Text.Split(' ')[0] + " (" + Modulo.Modulo_ID + ") - Alm: " + Modulo.MovMotor.CodigoAlarme;
@ -117,7 +119,7 @@ namespace AgroBase.Forms
lblM_Sentido.Text = "Sentido: " + Enum.GetName(typeof(Sentido), Modulo.MovMotor.Sentido); lblM_Sentido.Text = "Sentido: " + Enum.GetName(typeof(Sentido), Modulo.MovMotor.Sentido);
Label lblM_Temperatura = pnlFundo.Controls.OfType<Label>().FirstOrDefault(ctrl => ctrl.Name == "lbl" + Modulo.Modulo_ID + "M_Temperatura"); Label lblM_Temperatura = pnlFundo.Controls.OfType<Label>().FirstOrDefault(ctrl => ctrl.Name == "lbl" + Modulo.Modulo_ID + "M_Temperatura");
lblM_Temperatura.Text = "Temperatura: " + Modulo.MovMotor.Temperatura.ToString("0.00") + "ºC"; lblM_Temperatura.Text = "Temperatura: " + Modulo.MovMotor.Temperatura.ToString("0.00") + "ºC";
lblM_Temperatura.ForeColor = Modulo.MovMotor.CodigoAlarme > 0 ? Color.Red : Color.Black; lblM_Temperatura.ForeColor = sTMP?.Iniciado ?? false ? Color.Green : Color.Red;
Label lblM_Corrente = pnlFundo.Controls.OfType<Label>().FirstOrDefault(ctrl => ctrl.Name == "lbl" + Modulo.Modulo_ID + "M_Corrente"); Label lblM_Corrente = pnlFundo.Controls.OfType<Label>().FirstOrDefault(ctrl => ctrl.Name == "lbl" + Modulo.Modulo_ID + "M_Corrente");
lblM_Corrente.Text = "Corrente: " + Modulo.MovMotor.Corrente_Motor.ToString("0.00") + "A"; lblM_Corrente.Text = "Corrente: " + Modulo.MovMotor.Corrente_Motor.ToString("0.00") + "A";
Label lblM_Tensao = pnlFundo.Controls.OfType<Label>().FirstOrDefault(ctrl => ctrl.Name == "lbl" + Modulo.Modulo_ID + "M_Tensao"); Label lblM_Tensao = pnlFundo.Controls.OfType<Label>().FirstOrDefault(ctrl => ctrl.Name == "lbl" + Modulo.Modulo_ID + "M_Tensao");
@ -376,16 +378,18 @@ namespace AgroBase.Forms
private void pnlOrientacaoGPS_Paint(object sender, PaintEventArgs e) private void pnlOrientacaoGPS_Paint(object sender, PaintEventArgs e)
{ {
double Angulo = GPSService.UltimaLeitura.OrientacaoReal; var _Sensoriamento = Variaveis.OperacaoEmAndamento.Sensoriamento;
double AnguloMovimento = GPSService.UltimaLeitura.OrientacaoReal; double Angulo = _Sensoriamento.Gps.OrientacaoReal;
double AnguloMovimento = _Sensoriamento.Gps.OrientacaoMovimento;
FuncoesGlobais.DesenharInclinacao((Panel)sender, e, (float)Angulo, -90, (float)AnguloMovimento); FuncoesGlobais.DesenharInclinacao((Panel)sender, e, (float)Angulo, -90, (float)AnguloMovimento);
} }
private void pnlOrientacaoMagnetometro_Paint(object sender, PaintEventArgs e) private void pnlOrientacaoMagnetometro_Paint(object sender, PaintEventArgs e)
{ {
var Imu = Variaveis.OperacaoEmAndamento.DispSen?.Dados?.DadosLeitura?.SensoresIMU?.DefaultIfEmpty()?.FirstOrDefault(); var _Sensoriamento = Variaveis.OperacaoEmAndamento.Sensoriamento;
double Angulo = Imu?.Yaw ?? 0; double Angulo = _Sensoriamento.IMU.Rotacao;
FuncoesGlobais.DesenharInclinacao((Panel)sender, e, (float)Angulo, -90); double AnguloCorrigido = _Sensoriamento.IMU.RotacaoCorrigida;
FuncoesGlobais.DesenharInclinacao((Panel)sender, e, (float)Angulo, -90, (float)AnguloCorrigido);
} }

View File

@ -41,22 +41,24 @@ namespace AgroBase.Forms
private async Task tmrLeitura_Tick() private async Task tmrLeitura_Tick()
{ {
lblAltitude.Text = "Altitude: " + GPSService.UltimaLeitura.Altitude.ToString("0.0") + " m"; var Gps = Variaveis.OperacaoEmAndamento.Sensoriamento.Gps;
lblDatahora.Text = "Ultima Leitura: " + GPSService.UltimaLeitura.DataHora.ToString("HH:mm:ss");
txtLatitude.Text = GPSService.UltimaLeitura.Latitude.ToString(); lblAltitude.Text = "Altitude: " + Gps.Altitude.ToString("0.0") + " m";
txtLongitude.Text = GPSService.UltimaLeitura.Longitude.ToString(); lblDatahora.Text = "Ultima Leitura: " + Gps.DataHora.ToString("HH:mm:ss");
lblPrecisaoHorizontal.Text = "Precisão Horizontal: " + GPSService.UltimaLeitura.PrecisaoHorizontal.ToString("0.00"); txtLatitude.Text = Gps.Latitude.ToString();
lblPrecisaoCm.Text = "Precisão Leitura: " + GPSService.UltimaLeitura.PrecisaoCm.ToString("0.00") + " cm"; txtLongitude.Text = Gps.Longitude.ToString();
lblSatelites.Text = "Satélites Visíveis: " + GPSService.UltimaLeitura.NumeroSatelites.ToString(); lblPrecisaoHorizontal.Text = "Precisão Horizontal: " + Gps.PrecisaoHorizontal.ToString("0.00");
lblVelocidade.Text = "Velocidade: " + GPSService.UltimaLeitura.Velocidade.ToString("0.00") + " km/h"; lblPrecisaoCm.Text = "Precisão Leitura: " + Gps.PrecisaoCm.ToString("0.00") + " cm";
lblOrientacao.Text = "Orientação: " + GPSService.UltimaLeitura.OrientacaoReal.ToString("0.00") + "º (" + GPSService.UltimaLeitura.OrientacaoMovimento.ToString("0.00") + "º)"; lblSatelites.Text = "Satélites Visíveis: " + Gps.NumeroSatelites.ToString();
lblCursoVerdadeiro.Text = "Curso Verdadeiro: " + GPSService.UltimaLeitura.CursoVerdadeiro.ToString("0.00") + "º"; lblVelocidade.Text = "Velocidade: " + Gps.Velocidade.ToString("0.00") + " km/h";
lblVariacaoMagnetica.Text = "Variação Magnética: " + GPSService.UltimaLeitura.VariacaoMagnetica.ToString("0.00") + "º"; lblOrientacao.Text = "Orientação: " + Gps.OrientacaoReal.ToString("0.00") + "º (" + Gps.OrientacaoMovimento.ToString("0.00") + "º)";
lblFix.Text = "Correção: " + GPSService.UltimaLeitura.QualidadeFix.ToString(); lblCursoVerdadeiro.Text = "Curso Verdadeiro: " + Gps.CursoVerdadeiro.ToString("0.00") + "º";
lblVariacaoMagnetica.Text = "Variação Magnética: " + Gps.VariacaoMagnetica.ToString("0.00") + "º";
lblFix.Text = "Correção: " + Gps.QualidadeFix.ToString();
if (chbSalvar.Checked) if (chbSalvar.Checked)
{ {
GPSModel leitura = GPSService.UltimaLeitura.Clone(); GPSModel leitura = Gps.Clone();
if (leitura.Distancia >= TrajetoriaMapaOperacaoModel.DistanciaEntrePontos) if (leitura.Distancia >= TrajetoriaMapaOperacaoModel.DistanciaEntrePontos)
{ {
@ -69,7 +71,7 @@ namespace AgroBase.Forms
if (GPSService.Iniciado) if (GPSService.Iniciado)
{ {
int ID = Convert.ToInt32(Variaveis.IsAgroMonitor ? Variaveis.OperacaoEmAndamento.DispSen.Dados.LoRaParametrosBase.address : Variaveis.ConexaoLoRa.parametros.address); int ID = Convert.ToInt32(Variaveis.IsAgroMonitor ? Variaveis.OperacaoEmAndamento.DispSen.Dados.LoRaParametrosBase.address : Variaveis.ConexaoLoRa.parametros.address);
GPSService.EnviarCoordenadasParaMapa(GPSService.UltimaLeitura.Latitude, GPSService.UltimaLeitura.Longitude, GPSService.UltimaLeitura.AnguloCarroDefinido, true, ID); GPSService.EnviarCoordenadasParaMapa(Gps.Latitude, Gps.Longitude, Gps.AnguloCarroDefinido, true, ID);
} }
} }

View File

@ -62,7 +62,7 @@ namespace AgroBase.Forms
private void btnRegistrarPontos_Click(object sender, EventArgs e) private void btnRegistrarPontos_Click(object sender, EventArgs e)
{ {
GPSModel P1 = GPSService.UltimaLeitura.Clone(); GPSModel P1 = Variaveis.OperacaoEmAndamento.Sensoriamento.Gps.Clone();
if (Pontos[idxRua].Count == 0) if (Pontos[idxRua].Count == 0)
{ {
@ -127,8 +127,8 @@ namespace AgroBase.Forms
{ {
try try
{ {
double angulo = GPSService.UltimaLeitura.AnguloCarroDefinido; double angulo = Variaveis.OperacaoEmAndamento.Sensoriamento.Gps.AnguloCarroDefinido;
double anguloCorredor = GPSService.UltimaLeitura.OrientacaoMovimento; double anguloCorredor = Variaveis.OperacaoEmAndamento.Sensoriamento.Gps.OrientacaoMovimento;
FuncoesGlobais.DesenharInclinacao((Panel)sender, e, (float)angulo, 90, (float)anguloCorredor); FuncoesGlobais.DesenharInclinacao((Panel)sender, e, (float)angulo, 90, (float)anguloCorredor);
} }
catch { } catch { }
@ -177,12 +177,14 @@ namespace AgroBase.Forms
ultimoPonto = Pontos[Pontos.Count - 1][Pontos[Pontos.Count - 1].Count - 1]; ultimoPonto = Pontos[Pontos.Count - 1][Pontos[Pontos.Count - 1].Count - 1];
} }
var Gps = Variaveis.OperacaoEmAndamento.Sensoriamento.Gps;
pnlOrientacaoGps.Invalidate(); pnlOrientacaoGps.Invalidate();
lblStatusGPS.Text = $"GPS - Precisão: {GPSService.UltimaLeitura.PrecisaoCm} cm, " + lblStatusGPS.Text = $"GPS - Precisão: {Gps.PrecisaoCm} cm, " +
$"Coreção: {GPSService.UltimaLeitura.QualidadeFix}, " + $"Coreção: {Gps.QualidadeFix}, " +
$"Satélites: {GPSService.UltimaLeitura.NumeroSatelites}, " + $"Satélites: {Gps.NumeroSatelites}, " +
$"Distância: {(!add ? 0 : GPSUtils.DistanciaEntrePontos(ultimoPonto, GPSService.UltimaLeitura) ).ToString("0.00")} m, " + $"Distância: {(!add ? 0 : GPSUtils.DistanciaEntrePontos(ultimoPonto, Gps) ).ToString("0.00")} m, " +
$"Orientação: {(!add ? 0 : GPSUtils.CalcularOrientacao(ultimoPonto, GPSService.UltimaLeitura)).ToString("0.00")}º"; $"Orientação: {(!add ? 0 : GPSUtils.CalcularOrientacao(ultimoPonto, Gps)).ToString("0.00")}º";
} }
private void dgRuas_CellDoubleClick(object sender, DataGridViewCellEventArgs e) private void dgRuas_CellDoubleClick(object sender, DataGridViewCellEventArgs e)

View File

@ -161,7 +161,7 @@ namespace AgroBase.Forms
foreach (var Dispositivo in Dispositivos) foreach (var Dispositivo in Dispositivos)
{ {
Dispositivo.Funcoes.ForEach(x => Pinos.Add(Dispositivo.ID + " " + Enum.GetName(typeof(FuncoesPinout), x))); Dispositivo.Funcoes?.ForEach(x => Pinos.Add(Dispositivo.ID + " " + Enum.GetName(typeof(FuncoesPinout), x)));
} }
List<ComboBox> cmbs = this.Controls.OfType<ComboBox>().Where(x => x.Name.Contains("cmb")).ToList(); List<ComboBox> cmbs = this.Controls.OfType<ComboBox>().Where(x => x.Name.Contains("cmb")).ToList();

View File

@ -59,11 +59,11 @@ namespace AgroBase.Forms
private async Task tmrLeitura_Tick() private async Task tmrLeitura_Tick()
{ {
var Imu = Variaveis.OperacaoEmAndamento.DispSen?.Dados?.DadosLeitura?.SensoresIMU?.FirstOrDefault(); var Imu = Variaveis.OperacaoEmAndamento.Sensoriamento.IMU;
AnguloX = Imu?.Roll ?? 0; AnguloX = Imu.InclinacaoLateral;
AnguloY = Imu?.Pitch ?? 0; AnguloY = Imu.InclinacaoFrontal;
AnguloZ = Imu?.Yaw ?? 0; AnguloZ = Imu.Rotacao;
OrientacaoMagnetica = Imu?.YawFixed ?? 0; OrientacaoMagnetica = Imu.RotacaoCorrigida;
AtualizarDadosTela(); AtualizarDadosTela();
} }

View File

@ -332,7 +332,7 @@ namespace AgroBase.Models
private void DrawObstacle(Graphics g, float xRobot, float yRobot, Color pointColor, Color borderColor, float angle, Obstaculo obstaculo, float PxToCm) private void DrawObstacle(Graphics g, float xRobot, float yRobot, Color pointColor, Color borderColor, float angle, Obstaculo obstaculo, float PxToCm)
{ {
GPSModel posicaoRobo = GPSService.UltimaLeitura; GPSModel posicaoRobo = Variaveis.OperacaoEmAndamento.Sensoriamento.Gps;
GPSModel posicaoObstaculo = GPSUtils.GerarPontoDeslocado(posicaoRobo, angle, obstaculo.DistanciaMedia_mm / 1000); GPSModel posicaoObstaculo = GPSUtils.GerarPontoDeslocado(posicaoRobo, angle, obstaculo.DistanciaMedia_mm / 1000);
float x = xRobot + (float)((posicaoObstaculo.Longitude - posicaoRobo.Longitude) * _zoom); float x = xRobot + (float)((posicaoObstaculo.Longitude - posicaoRobo.Longitude) * _zoom);

View File

@ -2342,6 +2342,7 @@ namespace AgroBase.Models.Modules
case S_Code.sTMP: case S_Code.sTMP:
{ {
double temperatura = ConverterByteParaDouble(data, 2); double temperatura = ConverterByteParaDouble(data, 2);
Console.WriteLine("temperatura ET: " + temperatura);
DefinirOuCriar(ID_Num, posicao, componente, new List<dynamic>() { temperatura }); DefinirOuCriar(ID_Num, posicao, componente, new List<dynamic>() { temperatura });
break; break;
} }

View File

@ -2984,6 +2984,7 @@ namespace AgroBase.Models
return new DateTime().AddSeconds(TempoDecorridoSeg); return new DateTime().AddSeconds(TempoDecorridoSeg);
} }
} }
public OperacaoSensoriamentoLogImuModel IMU { get; set; }
public OperacaoSensoriamentoLogAtuModel Atuador { get; set; } public OperacaoSensoriamentoLogAtuModel Atuador { get; set; }
public OperacaoSensoriamentoLogMvdModel Movimentacao { get; set; } public OperacaoSensoriamentoLogMvdModel Movimentacao { get; set; }
public OperacaoSensoriamentoLogBateriaModel Bateria { get; set; } public OperacaoSensoriamentoLogBateriaModel Bateria { get; set; }
@ -3002,6 +3003,8 @@ namespace AgroBase.Models
var _DispSen = Variaveis.OperacaoEmAndamento.DispSen; var _DispSen = Variaveis.OperacaoEmAndamento.DispSen;
var _Controle = Variaveis.OperacaoEmAndamento.Controle; var _Controle = Variaveis.OperacaoEmAndamento.Controle;
_DispMvd?.Dados?.Modulos?.ForEach(x => x.AtualizarSensoresMotor());
Variaveis.OperacaoEmAndamento.AtualizarDispositiviosIndividuaisConectados(); Variaveis.OperacaoEmAndamento.AtualizarDispositiviosIndividuaisConectados();
Variaveis.OperacaoEmAndamento.AtualizarModulosConectados(); Variaveis.OperacaoEmAndamento.AtualizarModulosConectados();
Variaveis.OperacaoEmAndamento.AtualizarOperacaoLiberada(); Variaveis.OperacaoEmAndamento.AtualizarOperacaoLiberada();
@ -3019,6 +3022,19 @@ namespace AgroBase.Models
? _DispAtu.Dados.VolumeVazaoML / totalAtuacoes ? _DispAtu.Dados.VolumeVazaoML / totalAtuacoes
: 0.0; : 0.0;
var sIMU = _DispSen?.Dados?.DadosLeitura?.SensoresIMU?.FirstOrDefault();
var dadosIMU = sIMU != null ? new OperacaoSensoriamentoLogImuModel()
{
Iniciado = sIMU.Iniciado,
InclinacaoLateral = sIMU.Roll,
InclinacaoFrontal = sIMU.Pitch,
Rotacao = sIMU.Yaw,
RotacaoCorrigida = sIMU.YawFixed,
Altitude = sIMU.Altitude,
Pressao = sIMU.Pressao,
Temperatura = sIMU.Temperatura
} : new OperacaoSensoriamentoLogImuModel();
var dadosAtuador = _DispAtu != null ? new OperacaoSensoriamentoLogAtuModel() var dadosAtuador = _DispAtu != null ? new OperacaoSensoriamentoLogAtuModel()
{ {
HerbicidaConsumido = _DispAtu.Dados.VolumeVazaoML, HerbicidaConsumido = _DispAtu.Dados.VolumeVazaoML,
@ -3048,6 +3064,7 @@ namespace AgroBase.Models
var S36V = _DispSen?.Dados?.DadosLeitura?.SensoresCorrente?.FirstOrDefault(x => x.ID == "AB36V"); var S36V = _DispSen?.Dados?.DadosLeitura?.SensoresCorrente?.FirstOrDefault(x => x.ID == "AB36V");
var dadosBateria = S36V != null ? new OperacaoSensoriamentoLogBateriaModel() var dadosBateria = S36V != null ? new OperacaoSensoriamentoLogBateriaModel()
{ {
Iniciado = S36V?.Iniciado ?? false,
_dt = S36V?._dt ?? 0, _dt = S36V?._dt ?? 0,
PorcentagemBateria = FuncoesMatematicas.Clamp(_DispSen.Dados.ContadorCarga.PercentualBateria, 0, 100), PorcentagemBateria = FuncoesMatematicas.Clamp(_DispSen.Dados.ContadorCarga.PercentualBateria, 0, 100),
BateriaConsumida = FuncoesMatematicas.Clamp(_DispSen.Dados.ContadorCarga.PercentualConsumido, 0, 100), BateriaConsumida = FuncoesMatematicas.Clamp(_DispSen.Dados.ContadorCarga.PercentualConsumido, 0, 100),
@ -3107,6 +3124,7 @@ namespace AgroBase.Models
DataInicio = Variaveis.OperacaoEmAndamento.DataInicio, DataInicio = Variaveis.OperacaoEmAndamento.DataInicio,
DataFim = Variaveis.OperacaoEmAndamento.DataFim, DataFim = Variaveis.OperacaoEmAndamento.DataFim,
TempoDecorridoSeg = Variaveis.OperacaoEmAndamento.TempoDecorridoSegs, TempoDecorridoSeg = Variaveis.OperacaoEmAndamento.TempoDecorridoSegs,
IMU = dadosIMU,
Atuador = dadosAtuador, Atuador = dadosAtuador,
Movimentacao = dadosMovimentacao, Movimentacao = dadosMovimentacao,
Bateria = dadosBateria, Bateria = dadosBateria,
@ -3143,6 +3161,18 @@ namespace AgroBase.Models
} }
} }
public class OperacaoSensoriamentoLogImuModel
{
public bool Iniciado { get; set; }
public double InclinacaoLateral { get; set; }
public double InclinacaoFrontal { get; set; }
public double Rotacao { get; set; }
public double RotacaoCorrigida { get; set; }
public double Temperatura { get; set; }
public double Pressao { get; set; }
public double Altitude { get; set; }
}
public class OperacaoSensoriamentoLogAtuModel public class OperacaoSensoriamentoLogAtuModel
{ {
public double HerbicidaConsumido { get; set;} public double HerbicidaConsumido { get; set;}
@ -3222,6 +3252,7 @@ namespace AgroBase.Models
public class OperacaoSensoriamentoLogBateriaModel public class OperacaoSensoriamentoLogBateriaModel
{ {
public bool Iniciado { get; set; }
public double _dt { get; set; } public double _dt { get; set; }
public double PorcentagemBateria { get; set; } public double PorcentagemBateria { get; set; }
public double BateriaConsumida { get; set; } public double BateriaConsumida { get; set; }

View File

@ -775,12 +775,12 @@ namespace AgroBase.Models
// Supondo que a distância seja em metros e utilizando uma aproximação simples da Terra como esfera // Supondo que a distância seja em metros e utilizando uma aproximação simples da Terra como esfera
// para converter distância e ângulo em mudança de latitude/longitude. // para converter distância e ângulo em mudança de latitude/longitude.
double deltaLatitude = (DistanciaMedia * Math.Cos(anguloRad)) / 111111; // Dividindo por 111111 para converter metros em graus double deltaLatitude = (DistanciaMedia * Math.Cos(anguloRad)) / 111111; // Dividindo por 111111 para converter metros em graus
double deltaLongitude = (DistanciaMedia * Math.Sin(anguloRad)) / (111111 * Math.Cos(GPSService.UltimaLeitura.Latitude * (Math.PI / 180.0))); double deltaLongitude = (DistanciaMedia * Math.Sin(anguloRad)) / (111111 * Math.Cos(Variaveis.OperacaoEmAndamento.Sensoriamento.Gps.Latitude * (Math.PI / 180.0)));
return new GPSModel return new GPSModel
{ {
Latitude = GPSService.UltimaLeitura.Latitude + deltaLatitude, Latitude = Variaveis.OperacaoEmAndamento.Sensoriamento.Gps.Latitude + deltaLatitude,
Longitude = GPSService.UltimaLeitura.Longitude + deltaLongitude Longitude = Variaveis.OperacaoEmAndamento.Sensoriamento.Gps.Longitude + deltaLongitude
}; };
} }
} }

View File

@ -32,9 +32,9 @@ namespace AgroBase.Models
public double TempoEntreLeituras { get; private set; } public double TempoEntreLeituras { get; private set; }
private void AtualizarTempoEntreLeituras() private void AtualizarTempoEntreLeituras()
{ {
double dt = Math.Min((1.0 / GPSService.TaxaAmostragemHz), (UltimaAtualizacaoDados - GPSService.UltimaLeitura.Momento).TotalSeconds); double dt = Math.Min((1.0 / GPSService.TaxaAmostragemHz), (UltimaAtualizacaoDados - Variaveis.OperacaoEmAndamento.Sensoriamento.Gps.Momento).TotalSeconds);
TempoEntreLeituras = dt; TempoEntreLeituras = dt;
UltimaAtualizacaoDados = GPSService.UltimaLeitura.Momento; UltimaAtualizacaoDados = Variaveis.OperacaoEmAndamento.Sensoriamento.Gps.Momento;
} }
public List<List<GPSModel>> RuasPlantacao { get; set; } public List<List<GPSModel>> RuasPlantacao { get; set; }
@ -77,8 +77,8 @@ namespace AgroBase.Models
{ {
get get
{ {
double distPP = GPSUtils.DistanciaEntrePontos(GPSService.UltimaLeitura, PrimeiroPontoRuaMapa); double distPP = GPSUtils.DistanciaEntrePontos(Variaveis.OperacaoEmAndamento.Sensoriamento.Gps, PrimeiroPontoRuaMapa);
double distUP = GPSUtils.DistanciaEntrePontos(GPSService.UltimaLeitura, UltimoPontoRuaMapa); double distUP = GPSUtils.DistanciaEntrePontos(Variaveis.OperacaoEmAndamento.Sensoriamento.Gps, UltimoPontoRuaMapa);
// 0 para mais próximo do primeiro ponto da rua (ENTRANDO) // 0 para mais próximo do primeiro ponto da rua (ENTRANDO)
// 1 para mais próximo do último ponto da rua (SAINDO) // 1 para mais próximo do último ponto da rua (SAINDO)
@ -118,7 +118,7 @@ namespace AgroBase.Models
{ {
new PontoTrajetoriaModel(TipoPontoRua.PosicaoRobo) new PontoTrajetoriaModel(TipoPontoRua.PosicaoRobo)
{ {
Posicao = GPSService.UltimaLeitura, Posicao = Variaveis.OperacaoEmAndamento.Sensoriamento.Gps,
LarguraCorredor = 1.0, LarguraCorredor = 1.0,
idxCorredor = CorredorAtual?.Idx ?? 0, idxCorredor = CorredorAtual?.Idx ?? 0,
Visitado = true Visitado = true
@ -209,7 +209,7 @@ namespace AgroBase.Models
private void AtualizarAnguloCaminho() private void AtualizarAnguloCaminho()
{ {
PontoTrajetoriaModel pontoComparar = PontoAtual.Aproximando ? PontoAtual : ProximoPonto != null ? ProximoPonto : PontoAtual; PontoTrajetoriaModel pontoComparar = PontoAtual.Aproximando ? PontoAtual : ProximoPonto != null ? ProximoPonto : PontoAtual;
AnguloCaminho = GPSUtils.CalcularOrientacao(GPSService.UltimaLeitura, pontoComparar.Posicao); AnguloCaminho = GPSUtils.CalcularOrientacao(Variaveis.OperacaoEmAndamento.Sensoriamento.Gps, pontoComparar.Posicao);
} }
[JsonProperty] [JsonProperty]
public double DistanciaEsquerda { get; private set; } public double DistanciaEsquerda { get; private set; }
@ -217,8 +217,8 @@ namespace AgroBase.Models
public double DistanciaDireita { get; private set; } public double DistanciaDireita { get; private set; }
private void AtualizarDistanciasLaterais() private void AtualizarDistanciasLaterais()
{ {
DistanciaEsquerda = CalcularDistanciaLateral(true, GPSService.UltimaLeitura, CorredorAtual?.idxRuaEsquerda ?? 0, PontoAtual?.Direcao ?? DirecaoCarroRua.Ida); DistanciaEsquerda = CalcularDistanciaLateral(true, Variaveis.OperacaoEmAndamento.Sensoriamento.Gps, CorredorAtual?.idxRuaEsquerda ?? 0, PontoAtual?.Direcao ?? DirecaoCarroRua.Ida);
DistanciaDireita = CalcularDistanciaLateral(false, GPSService.UltimaLeitura, CorredorAtual?.idxRuaDireita ?? 0, PontoAtual?.Direcao ?? DirecaoCarroRua.Ida); DistanciaDireita = CalcularDistanciaLateral(false, Variaveis.OperacaoEmAndamento.Sensoriamento.Gps, CorredorAtual?.idxRuaDireita ?? 0, PontoAtual?.Direcao ?? DirecaoCarroRua.Ida);
} }
public double CalcularDistanciaLateral(bool ladoEsquerdo, GPSModel posicaoAtual, int idxRua, DirecaoCarroRua direcaoAtual) public double CalcularDistanciaLateral(bool ladoEsquerdo, GPSModel posicaoAtual, int idxRua, DirecaoCarroRua direcaoAtual)
@ -875,7 +875,7 @@ namespace AgroBase.Models
idxCorredor = 0, idxCorredor = 0,
idxPonto = 0, idxPonto = 0,
idxPontoCorredor = 0, idxPontoCorredor = 0,
Posicao = GPSService.UltimaLeitura, Posicao = Variaveis.OperacaoEmAndamento.Sensoriamento.Gps,
Direcao = direcaoAtual, Direcao = direcaoAtual,
Orientacao = 0, Orientacao = 0,
Visitado = true, Visitado = true,
@ -1151,7 +1151,7 @@ namespace AgroBase.Models
public void AjustarTrajetoriaParaDesvio(Obstaculo obstaculo) public void AjustarTrajetoriaParaDesvio(Obstaculo obstaculo)
{ {
GPSModel posicaoAtual = GPSService.UltimaLeitura; GPSModel posicaoAtual = Variaveis.OperacaoEmAndamento.Sensoriamento.Gps;
double distanciaObstaculo = ((double)obstaculo.DistanciaMedia_mm / 1000); double distanciaObstaculo = ((double)obstaculo.DistanciaMedia_mm / 1000);
double larguraObstaculo = ((double)obstaculo.Largura_mm / 1000); double larguraObstaculo = ((double)obstaculo.Largura_mm / 1000);
@ -1392,7 +1392,7 @@ namespace AgroBase.Models
private void AtualizarOrientacaoAtual() private void AtualizarOrientacaoAtual()
{ {
OrientacaoAtual = GPSUtils.CalcularOrientacao(GPSService.UltimaLeitura, Posicao); OrientacaoAtual = GPSUtils.CalcularOrientacao(Variaveis.OperacaoEmAndamento.Sensoriamento.Gps, Posicao);
} }
private void AtualizarOrientacaoAnterior() private void AtualizarOrientacaoAnterior()
@ -1446,7 +1446,7 @@ namespace AgroBase.Models
private void AtualizarDistanciaAtual() private void AtualizarDistanciaAtual()
{ {
DistanciaAtual = GPSUtils.DistanciaEntrePontos(GPSService.UltimaLeitura, Posicao); DistanciaAtual = GPSUtils.DistanciaEntrePontos(Variaveis.OperacaoEmAndamento.Sensoriamento.Gps, Posicao);
} }
private void AtualizarDistanciaAnterior() private void AtualizarDistanciaAnterior()

View File

@ -716,10 +716,13 @@ namespace AgroBase.Services
{ {
double anguloFinal = 0.0; double anguloFinal = 0.0;
bool witIniciado = Variaveis.OperacaoEmAndamento.DispSen.Dados?.DadosLeitura?.SensoresIMU?.FirstOrDefault()?.Iniciado ?? false; bool imuIniciado = Variaveis.OperacaoEmAndamento.Sensoriamento.IMU.Iniciado;
bool gpsIniciado = Iniciado; bool gpsIniciado = Iniciado;
if (imuIniciado)
{
Variaveis.OperacaoEmAndamento.DispSen.Dados?.DadosLeitura?.SensoresIMU?.FirstOrDefault()?.AtualizarOffset(UltimaLeitura); Variaveis.OperacaoEmAndamento.DispSen.Dados?.DadosLeitura?.SensoresIMU?.FirstOrDefault()?.AtualizarOffset(UltimaLeitura);
}
if (gpsIniciado) if (gpsIniciado)
{ {
@ -735,10 +738,10 @@ namespace AgroBase.Services
anguloFinal = anguloGPS; anguloFinal = anguloGPS;
} }
else if (witIniciado) else if (imuIniciado)
{ {
// Apenas o WT901C está disponível // Apenas o WT901C está disponível
anguloFinal = Variaveis.OperacaoEmAndamento.DispSen.Dados?.DadosLeitura?.SensoresIMU?.FirstOrDefault()?.YawFixed ?? -1; anguloFinal = Variaveis.OperacaoEmAndamento.Sensoriamento.IMU.RotacaoCorrigida;
} }
else else
{ {

View File

@ -796,7 +796,7 @@ namespace AgroBase.Services
{ {
if (Iniciado && !Variaveis.IsAgroMonitor) if (Iniciado && !Variaveis.IsAgroMonitor)
{ {
double TemperaturaCampo = Variaveis.OperacaoEmAndamento.DispSen.Dados?.DadosLeitura?.SensoresIMU?.FirstOrDefault()?.Temperatura ?? -1; double TemperaturaCampo = Variaveis.OperacaoEmAndamento.Sensoriamento.IMU.Temperatura;
(bool dirOperante, List<string> dirModsFalha) = Variaveis.OperacaoEmAndamento.DispMvd.Dados.StatusModulosDIR(Variaveis.OperacaoEmAndamento.Controle.TipoMovimento); (bool dirOperante, List<string> dirModsFalha) = Variaveis.OperacaoEmAndamento.DispMvd.Dados.StatusModulosDIR(Variaveis.OperacaoEmAndamento.Controle.TipoMovimento);
(bool movEsqOperante, List<string> movEsqModsFalha) = Variaveis.OperacaoEmAndamento.DispMvd.Dados.StatusModulosMOV(Direcao.Esquerda); (bool movEsqOperante, List<string> movEsqModsFalha) = Variaveis.OperacaoEmAndamento.DispMvd.Dados.StatusModulosMOV(Direcao.Esquerda);
@ -821,8 +821,8 @@ namespace AgroBase.Services
}, },
Coordenadas = new LoRaProtocoloTransmissaoCoordenadasModel() Coordenadas = new LoRaProtocoloTransmissaoCoordenadasModel()
{ {
Latitude = GPSService.UltimaLeitura.Latitude, Latitude = Variaveis.OperacaoEmAndamento.Sensoriamento.Gps.Latitude,
Longitude = GPSService.UltimaLeitura.Longitude, Longitude = Variaveis.OperacaoEmAndamento.Sensoriamento.Gps.Longitude,
}, },
Sensores = new LoRaProtocoloTransmissaoSensoresModel() Sensores = new LoRaProtocoloTransmissaoSensoresModel()
{ {

View File

@ -33,7 +33,6 @@ namespace AgroBase.Services
public static List<T_Code> DispositivosMultiplos = new List<T_Code>() { T_Code.Bld, T_Code.Mks, T_Code.Mvd, T_Code.Oid, T_Code.Mov, T_Code.Dir }; public static List<T_Code> DispositivosMultiplos = new List<T_Code>() { T_Code.Bld, T_Code.Mks, T_Code.Mvd, T_Code.Oid, T_Code.Mov, T_Code.Dir };
public static List<DispositivoDetalhesModel> DispositivosMapeados = new List<DispositivoDetalhesModel>(); public static List<DispositivoDetalhesModel> DispositivosMapeados = new List<DispositivoDetalhesModel>();
private static Dictionary<string, int> TentativasPortas = new Dictionary<string, int>();
private static bool VarreduraEmAndamento = false; private static bool VarreduraEmAndamento = false;
@ -243,7 +242,7 @@ namespace AgroBase.Services
} }
} }
if (!ModbusService.Iniciado) /*if (!ModbusService.Iniciado)
{ {
AtualizarConsole($"{PortaCom} - Procurando dispositivos no barramento RS485"); AtualizarConsole($"{PortaCom} - Procurando dispositivos no barramento RS485");
bool DispModbus = await ProcuraDispositivoModbus(_Porta); bool DispModbus = await ProcuraDispositivoModbus(_Porta);
@ -253,7 +252,7 @@ namespace AgroBase.Services
AtualizarConsole("Barramento RS485 encontrado"); AtualizarConsole("Barramento RS485 encontrado");
continue; continue;
} }
} }*/
} }
catch (Exception ex) catch (Exception ex)
@ -280,7 +279,7 @@ namespace AgroBase.Services
await ProcurarDispositivosEthernet(); await ProcurarDispositivosEthernet();
} }
if (ModbusService.Iniciado) /*if (ModbusService.Iniciado)
{ {
await ProcuraDispositivoModbus(ModbusService._PortaModbus); await ProcuraDispositivoModbus(ModbusService._PortaModbus);
} }
@ -291,7 +290,7 @@ namespace AgroBase.Services
{ {
DispositivosMapeados.Remove(DispositivosMapeados.FirstOrDefault(x => x.Dispositivo == _Disp)); DispositivosMapeados.Remove(DispositivosMapeados.FirstOrDefault(x => x.Dispositivo == _Disp));
} }
} }*/
if (CanService.Iniciado) if (CanService.Iniciado)
{ {

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -25,7 +25,7 @@
<meta name="viewport" content="width=device-width, <meta name="viewport" content="width=device-width,
initial-scale=1.0, maximum-scale=1.0, user-scalable=no" /> initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
<style> <style>
#map_82b7108ea8cddae8bf3da5e9af968baa { #map_0a65390b914a9d20a49b9ea06134c652 {
position: relative; position: relative;
width: 100.0%; width: 100.0%;
height: 100.0%; height: 100.0%;
@ -39,14 +39,14 @@
<body> <body>
<div class="folium-map" id="map_82b7108ea8cddae8bf3da5e9af968baa" ></div> <div class="folium-map" id="map_0a65390b914a9d20a49b9ea06134c652" ></div>
</body> </body>
<script> <script>
var map_82b7108ea8cddae8bf3da5e9af968baa = L.map( var map_0a65390b914a9d20a49b9ea06134c652 = L.map(
"map_82b7108ea8cddae8bf3da5e9af968baa", "map_0a65390b914a9d20a49b9ea06134c652",
{ {
center: [0.0, 0.0], center: [0.0, 0.0],
crs: L.CRS.EPSG3857, crs: L.CRS.EPSG3857,
@ -60,13 +60,13 @@
var tile_layer_605bd35e89ca1ea18b377645f630a519 = L.tileLayer( var tile_layer_46f299708219af4df3a972d14ad0e238 = L.tileLayer(
"https://tile.openstreetmap.org/{z}/{x}/{y}.png", "https://tile.openstreetmap.org/{z}/{x}/{y}.png",
{"attribution": "\u0026copy; \u003ca href=\"https://www.openstreetmap.org/copyright\"\u003eOpenStreetMap\u003c/a\u003e contributors", "detectRetina": false, "maxNativeZoom": 19, "maxZoom": 19, "minZoom": 0, "noWrap": false, "opacity": 1, "subdomains": "abc", "tms": false} {"attribution": "\u0026copy; \u003ca href=\"https://www.openstreetmap.org/copyright\"\u003eOpenStreetMap\u003c/a\u003e contributors", "detectRetina": false, "maxNativeZoom": 19, "maxZoom": 19, "minZoom": 0, "noWrap": false, "opacity": 1, "subdomains": "abc", "tms": false}
); );
tile_layer_605bd35e89ca1ea18b377645f630a519.addTo(map_82b7108ea8cddae8bf3da5e9af968baa); tile_layer_46f299708219af4df3a972d14ad0e238.addTo(map_0a65390b914a9d20a49b9ea06134c652);
</script> </script>
@ -87,7 +87,7 @@
} }
trajeto_json_add({"features": []}); trajeto_json_add({"features": []});
trajeto_json.addTo(map_82b7108ea8cddae8bf3da5e9af968baa); trajeto_json.addTo(map_0a65390b914a9d20a49b9ea06134c652);
function adicionarGeometria(novaGeometria) { function adicionarGeometria(novaGeometria) {
trajeto_json.addData(novaGeometria); trajeto_json.addData(novaGeometria);
@ -145,7 +145,7 @@
var marcadorDinamico = L.marker([0, 0], { var marcadorDinamico = L.marker([0, 0], {
icon: customIcon icon: customIcon
}).addTo(map_82b7108ea8cddae8bf3da5e9af968baa); }).addTo(map_0a65390b914a9d20a49b9ea06134c652);
// Conectar ao broker MQTT // Conectar ao broker MQTT
const client = mqtt.connect('ws://localhost:9001'); // Use wss para conexão segura const client = mqtt.connect('ws://localhost:9001'); // Use wss para conexão segura
@ -183,7 +183,7 @@
marcadorDinamico.setRotationAngle(angulo); marcadorDinamico.setRotationAngle(angulo);
adicionarCoordenada("Tj", [novaLongitude, novaLatitude]); adicionarCoordenada("Tj", [novaLongitude, novaLatitude]);
map_82b7108ea8cddae8bf3da5e9af968baa.setView(novaPosicao, map_82b7108ea8cddae8bf3da5e9af968baa.getZoom()); map_0a65390b914a9d20a49b9ea06134c652.setView(novaPosicao, map_0a65390b914a9d20a49b9ea06134c652.getZoom());
}); });
function calcularOrientacao(P1latitude, P1longitude, P2latitude, P2longitude) { function calcularOrientacao(P1latitude, P1longitude, P2latitude, P2longitude) {

View File

@ -6,6 +6,7 @@
#include "C:\ZendionInc\agrobot_base\Firmware\Modulos\SerialService.h" #include "C:\ZendionInc\agrobot_base\Firmware\Modulos\SerialService.h"
#include "C:\ZendionInc\agrobot_base\Firmware\Modulos\CanService.h" #include "C:\ZendionInc\agrobot_base\Firmware\Modulos\CanService.h"
#include "C:\ZendionInc\agrobot_base\Firmware\Modulos\EepromService.h" #include "C:\ZendionInc\agrobot_base\Firmware\Modulos\EepromService.h"
#include "C:\ZendionInc\agrobot_base\Firmware\Modulos\I2CService.h"
#include "C:\ZendionInc\agrobot_base\Firmware\Modulos\Utils.h" #include "C:\ZendionInc\agrobot_base\Firmware\Modulos\Utils.h"
#include "C:\ZendionInc\agrobot_base\Firmware\Modulos\Pinout.h" #include "C:\ZendionInc\agrobot_base\Firmware\Modulos\Pinout.h"
#include "C:\ZendionInc\agrobot_base\Firmware\Modulos\ReleModel.h" #include "C:\ZendionInc\agrobot_base\Firmware\Modulos\ReleModel.h"
@ -34,10 +35,6 @@ int latenciaLoop = 0;
int qtdEnviosStatus = 0; int qtdEnviosStatus = 0;
int maxEnviosStatus = 5; int maxEnviosStatus = 5;
PinoModel _pinoSDA = PinoModel(1, CONTROLADOR, _INPUT);
PinoModel _pinoSCL = PinoModel(2, CONTROLADOR, _INPUT);
std::vector<Rele*> listaBicos; std::vector<Rele*> listaBicos;
std::vector<BombaPressurizadora*> listaBombas; std::vector<BombaPressurizadora*> listaBombas;
std::vector<SensorFluxo*> listaSensoresFluxo; std::vector<SensorFluxo*> listaSensoresFluxo;
@ -221,11 +218,8 @@ void ProcessarCfg(std::vector<uint8_t> data) {
int pinoSDA = data[4]; int pinoSDA = data[4];
int pinoSCL = data[5]; int pinoSCL = data[5];
if (pinoSDA != PINO_INVALIDO && pinoSCL != PINO_INVALIDO) { if (pinoSDA != PINO_INVALIDO && pinoSCL != PINO_INVALIDO) {
_pinoSDA = PinoModel(pinoSDA, CONTROLADOR, _INPUT); I2CService::DefinirPinos(pinoSDA, pinoSCL);
_pinoSCL = PinoModel(pinoSCL, CONTROLADOR, _INPUT); I2CService::IniciarI2C();
Wire.end();
Wire.begin(_pinoSDA.num, _pinoSCL.num);
PrintTela("I2C inicializado nos pinos SDA=" + String(pinoSDA) + " e SCL=" + String(pinoSCL));
} }
vTaskDelay(pdMS_TO_TICKS(100)); vTaskDelay(pdMS_TO_TICKS(100));
Conectado = Conectar; Conectado = Conectar;

View File

@ -0,0 +1,292 @@
#ifndef MuxService_h
#define MuxService_h
#include "SerialService.h"
#include <Wire.h>
#include <Adafruit_MCP23X17.h>
#include <Adafruit_ADS1X15.h>
#include <freertos/semphr.h>
class I2CService {
public:
static const constexpr uint8_t enderecoMux = 0x70;
static const constexpr uint8_t enderecoMcp = 0x20;
static const constexpr uint8_t enderecoAds = 0x48;
static bool I2CIniciado;
static bool MuxIniciado;
static bool McpIniciado;
static bool AdsIniciado;
static int canalAtivo;
static int idAtualUsandoI2C;
static Adafruit_MCP23X17 mcp;
static Adafruit_ADS1115 ads;
static SemaphoreHandle_t i2cMutex;
static void DefinirPinos(int sda, int scl) {
_pinoSDA = sda;
_pinoSCL = scl;
}
static bool IniciarI2C() {
if (I2CIniciado) {
Wire.end();
delay(10);
}
I2CIniciado = Wire.begin(_pinoSDA, _pinoSCL);
//Wire.setTimeout(50);
PrintTela("[I2C] I2C inicializado nos pinos SDA=" + String(_pinoSDA) + " e SCL=" + String(_pinoSCL) + " - Res " + I2CIniciado);
if (i2cMutex == nullptr) {
i2cMutex = xSemaphoreCreateMutex();
}
idAtualUsandoI2C = -1;
tempoEntradaI2C = 0;
return I2CIniciado;
}
static bool VerificaEnderecoBarramento(byte _Endereco, uint32_t timeoutMs = 50) {
if (!I2CIniciado) return false;
//Wire.setTimeout(timeoutMs);
unsigned long t0 = millis();
Wire.beginTransmission(_Endereco);
byte error = Wire.endTransmission();
if ((millis() - t0) > timeoutMs) {
PrintTela("[I2C] Timeout verificando endereco " + String(_Endereco));
return false;
}
return error == 0;
}
static bool SolicitarAcessoI2C(int idSensor = 0, int canalMux = -1, uint32_t timeoutMs = 200) {
if (!I2CIniciado) {
PrintTela("[I2C] Solicitacao de acesso negada para o sensor " + String(idSensor) + " - I2C Nao inicializado");
return false;
}
TickType_t timeoutTicks = pdMS_TO_TICKS(timeoutMs);
if (xSemaphoreTake(i2cMutex, timeoutTicks) != pdTRUE) {
PrintTela("[I2C] Timeout ao tentar acessar o I2C - ID: " + String(idSensor));
return false;
}
// Troca canal se necessário
if (canalMux >= 0 && !TrocarCanalMux(canalMux)) {
xSemaphoreGive(i2cMutex); // Libera caso a troca de canal falhe
return false;
}
idAtualUsandoI2C = idSensor;
tempoEntradaI2C = millis();
return true;
}
static void LiberarAcessoI2C(int idSensor = 0) {
if (idSensor == idAtualUsandoI2C) {
idAtualUsandoI2C = -1;
xSemaphoreGive(i2cMutex);
}
}
static int QuemEstaUsando() {
return idAtualUsandoI2C;
}
static void VerificarI2CPreso() {
if (idAtualUsandoI2C >= 0 && (millis() - tempoEntradaI2C > LimiteTempoI2C)) {
PrintTela("[I2C] Semáforo preso pelo ID %d — forçando liberação!\n", idAtualUsandoI2C);
LiberarAcessoI2C(idAtualUsandoI2C);
IniciarI2C();
}
}
static bool LeituraSegura(uint8_t addr, uint8_t* buffer, size_t qtd, uint8_t reg = 0xFF, uint32_t timeoutMs = 50) {
//Wire.setTimeout(timeoutMs);
unsigned long t0 = millis();
if (reg != 0xFF) {
Wire.beginTransmission(addr);
Wire.write(reg);
if (Wire.endTransmission(false) != 0) {
PrintTela("[I2C] Falha ao endTransmission (leitura)");
return false;
}
delay(1); // <----- ADICIONAR este delay aqui
}
size_t received = Wire.requestFrom((int)addr, (int)qtd);
if (received != qtd || (millis() - t0) > timeoutMs) {
PrintTela("[I2C] Timeout ou leitura incompleta");
return false;
}
for (size_t i = 0; i < qtd; i++) {
if (Wire.available()) {
buffer[i] = Wire.read();
} else {
PrintTela("[I2C] Dados insuficientes disponíveis");
return false;
}
}
return true;
}
static bool EscritaSegura(uint8_t addr, const uint8_t* dados, size_t qtd, uint32_t timeoutMs = 50) {
//Wire.setTimeout(timeoutMs);
unsigned long t0 = millis();
Wire.beginTransmission(addr);
for (size_t i = 0; i < qtd; i++) {
Wire.write(dados[i]);
}
int resultado = Wire.endTransmission();
if ((millis() - t0) > timeoutMs || resultado != 0) {
PrintTela("[I2C] Falha na escrita ou timeout");
return false;
}
return true;
}
static bool TrocarCanalMux(int canalMux) {
if (MuxIniciado && canalMux >= 0 && canalMux < 9) {
if (canalMux != canalAtivo) {
Wire.beginTransmission(enderecoMux);
Wire.write(1 << canalMux);
Wire.endTransmission();
PrintTela("[MUX] Canal alterado de " + String(canalAtivo) + " para " + String(canalMux));
canalAtivo = canalMux;
}
return true;
}
PrintTela("[MUX] Nao foi possivel trocar o canal para " + String(canalMux));
return false;
}
static void IniciarMUX(byte endereco = enderecoMux, bool Mandatorio = false) {
if (!I2CIniciado) {
PrintTela("[MUX] Impossivel iniciar TCA9548A, I2C nao iniciado!");
return;
}
PrintTela("[MUX] Iniciando TCA9548A...");
if (!MuxIniciado) {
SolicitarAcessoI2C();
Wire.beginTransmission(endereco);
MuxIniciado = (Wire.endTransmission() == 0);
if (!MuxIniciado) {
PrintTela("[MUX] TCA9548A nao Iniciado, endereco " + String(endereco) + " nao encontrado no barramento");
if (Mandatorio) {
PrintTela("[MUX] Conexão obrigatória, tentando novamente em 5 segundos...");
delay(5000);
IniciarMUX(endereco, Mandatorio);
}
else {
PrintTela("[MUX] TCA9548A nao mandatorio, continuando o fluxo...");
}
}
else {
canalAtivo = -1; // Nenhum canal ativo ainda
idAtualUsandoI2C = -1;
i2cMutex = xSemaphoreCreateMutex();
PrintTela("[MUX] TCA9548A Iniciado");
}
LiberarAcessoI2C();
}
else {
PrintTela("[MUX] TCA9548A ja Iniciado");
}
}
static void IniciarMCP(byte endereco = enderecoMcp, bool Mandatorio = false) {
if (!I2CIniciado) {
PrintTela("[MCP] Impossivel iniciar MCP23X17, I2C nao iniciado!");
return;
}
PrintTela("[MCP] Iniciando MCP23X17...");
if (!McpIniciado) {
SolicitarAcessoI2C();
McpIniciado = mcp.begin_I2C(endereco, &Wire);
if (!McpIniciado) {
PrintTela("[MCP] Erro ao iniciar MCP23X17!");
if (Mandatorio) {
PrintTela("[MCP] Conexão obrigatória, tentando novamente em 5 segundos...");
delay(5000);
IniciarMCP(endereco, Mandatorio);
}
else {
PrintTela("[MCP] MCP23X17 nao mandatorio, continuando o fluxo...");
}
}
else {
PrintTela("[MCP] MCP23X17 Iniciado");
}
LiberarAcessoI2C();
}
else {
PrintTela("[MCP] MCP23X17 ja Iniciado");
}
}
static void IniciarADS(byte endereco = enderecoAds, bool Mandatorio = false) {
if (!I2CIniciado) {
PrintTela("[ADS] Impossivel iniciar ADS1115, I2C nao iniciado!");
return;
}
PrintTela("[ADS] Iniciando ADS1115...");
if (!AdsIniciado) {
SolicitarAcessoI2C();
AdsIniciado = ads.begin(endereco, &Wire);
if (!AdsIniciado) {
PrintTela("[ADS] Erro ao iniciar ADS1115!");
if (Mandatorio) {
PrintTela("[ADS] Conexão obrigatória, tentando novamente em 5 segundos...");
delay(5000);
IniciarADS(endereco, Mandatorio);
}
else {
PrintTela("[ADS] ADS1115 nao mandatorio, continuando o fluxo...");
}
}
else {
ads.setGain(GAIN_ONE);
PrintTela("[ADS] ADS1115 Iniciado");
}
LiberarAcessoI2C();
}
else {
PrintTela("[ADS] ADS1115 ja Iniciado");
}
}
private:
static int _pinoSDA;
static int _pinoSCL;
static unsigned long tempoEntradaI2C;
static unsigned long LimiteTempoI2C;
};
int I2CService::_pinoSDA = 1;
int I2CService::_pinoSCL = 2;
unsigned long I2CService::LimiteTempoI2C = 100;
bool I2CService::I2CIniciado = false;
bool I2CService::MuxIniciado = false;
bool I2CService::McpIniciado = false;
Adafruit_MCP23X17 I2CService::mcp;
Adafruit_ADS1115 I2CService::ads;
bool I2CService::AdsIniciado = false;
int I2CService::canalAtivo = -1;
int I2CService::idAtualUsandoI2C = -1;
unsigned long I2CService::tempoEntradaI2C = 0;
SemaphoreHandle_t I2CService::i2cMutex = nullptr;
#endif

View File

@ -1,43 +0,0 @@
#ifndef MuxService_h
#define MuxService_h
#include "SerialService.h"
#include <Wire.h>
class MuxService {
public:
static const uint8_t enderecoMux = 0x70; // Padrão do TCA9548A
static bool Iniciado;
static int canalAtivo;
static void IniciarMUX() {
PrintTela("[MUX] Iniciando TCA9548A...");
Wire.beginTransmission(enderecoMux);
Iniciado = (Wire.endTransmission() == 0);
if (Iniciado) {
canalAtivo = -1; // Nenhum canal ativo ainda
PrintTela("[MUX] TCA9548A Iniciado");
}
else {
PrintTela("[MUX] TCA9548A nao Iniciado, endereco " + String(enderecoMux) + " nao encontrado no barramento");
}
}
static void SelecionarCanal(uint8_t canal) {
if (!Iniciado) return;
if (canalAtivo == canal) return; // Já está no canal certo
Wire.beginTransmission(enderecoMux);
Wire.write(1 << canal);
Wire.endTransmission();
PrintTela("[MUX] Canal alterado de " + String(canalAtivo) + " para " + String(canal));
canalAtivo = canal;
}
};
bool MuxService::Iniciado = false;
int MuxService::canalAtivo = -1;
#endif

View File

@ -1,17 +1,11 @@
#include "Enuns.h" #include "Enuns.h"
#include "SerialService.h" #include "SerialService.h"
#include <Wire.h> #include "I2CService.h"
#include <Adafruit_MCP23X17.h>
#include <Adafruit_ADS1X15.h>
#ifndef Pinout #ifndef Pinout
#define Pinout #define Pinout
#define PINO_INVALIDO 0xFF #define PINO_INVALIDO 0xFF
Adafruit_MCP23X17 mcp;
Adafruit_ADS1115 ads;
bool mcpInicializado = false;
bool adsInicializado = false;
class PinoModel { class PinoModel {
public: public:
@ -38,13 +32,15 @@ class PinoModel {
} }
} }
else if (barramento == EXPANSOR_GPIO) { else if (barramento == EXPANSOR_GPIO) {
if (mcpInicializado) { if (I2CService::McpIniciado) {
I2CService::SolicitarAcessoI2C();
if (tipo == _INPUT) { if (tipo == _INPUT) {
mcp.pinMode(num, INPUT); I2CService::mcp.pinMode(num, INPUT);
} else if (tipo == _OUTPUT) { } else if (tipo == _OUTPUT) {
mcp.pinMode(num, OUTPUT); I2CService::mcp.pinMode(num, OUTPUT);
set(statusInicial); set(statusInicial);
} }
I2CService::LiberarAcessoI2C();
} }
} }
} }
@ -59,8 +55,10 @@ class PinoModel {
pinMode(num, INPUT); pinMode(num, INPUT);
} }
else if (barramento == EXPANSOR_GPIO) { else if (barramento == EXPANSOR_GPIO) {
if (mcpInicializado) { if (I2CService::McpIniciado) {
mcp.pinMode(num, INPUT); I2CService::SolicitarAcessoI2C();
I2CService::mcp.pinMode(num, INPUT);
I2CService::LiberarAcessoI2C();
} }
} }
} }
@ -82,20 +80,25 @@ class PinoModel {
} }
} }
else if (barramento == EXPANSOR_GPIO) { else if (barramento == EXPANSOR_GPIO) {
if (mcpInicializado) { if (I2CService::McpIniciado) {
return mcp.digitalRead(num); I2CService::SolicitarAcessoI2C();
int leitura = I2CService::mcp.digitalRead(num);
I2CService::LiberarAcessoI2C();
return leitura;
} }
} }
else if (barramento == EXPANSOR_ADS) { else if (barramento == EXPANSOR_ADS) {
if (adsInicializado) { if (I2CService::AdsIniciado) {
double l = 0; I2CService::SolicitarAcessoI2C();
uint16_t l = 0;
for (int i = 0; i < leituras; i++) { for (int i = 0; i < leituras; i++) {
int leituraADC = (int)(ads.readADC_SingleEnded(num)); int leituraADC = (int)(I2CService::ads.readADC_SingleEnded(num));
int leitura12bits = map(leituraADC, 0, 32767, 0, 4095); int leitura12bits = map(leituraADC, 0, 32767, 0, 4095);
l += leitura12bits; l += leitura12bits;
delay(1); delay(1);
} }
return l / leituras; I2CService::LiberarAcessoI2C();
return (int)(l / leituras);
} }
} }
} }
@ -108,67 +111,15 @@ class PinoModel {
digitalWrite(num, status ? HIGH : LOW); digitalWrite(num, status ? HIGH : LOW);
} }
else if (barramento == EXPANSOR_GPIO) { else if (barramento == EXPANSOR_GPIO) {
if (mcpInicializado) { if (I2CService::McpIniciado) {
mcp.digitalWrite(num, status ? HIGH : LOW); I2CService::SolicitarAcessoI2C();
I2CService::mcp.digitalWrite(num, status ? HIGH : LOW);
I2CService::LiberarAcessoI2C();
} }
} }
} }
} }
}; };
void iniciarMCP(T_Code Modulo, String Mod_ID, int sda, int scl, byte endereco, bool Mandatorio = false) {
PrintTela("Iniciando MCP23X17...");
if (!mcpInicializado) {
bool init = Wire.begin(sda, scl);
String str = "SDA " + (String)sda + " SCL " + (String)scl + " Res " + init + " - ";
PrintTela(str, false);
if (!mcp.begin_I2C(endereco, &Wire)) {
mcpInicializado = false;
PrintTela("Erro ao iniciar MCP23X17!");
if (Mandatorio) {
PrintTela("Conexão obrigatória, tentando novamente em 5 segundos...");
//EnviarDadosSerial(Mod_ID, MontarProtocoloErro(Modulo));
delay(5000);
iniciarMCP(Modulo, Mod_ID, sda, scl, endereco, Mandatorio);
}
else {
PrintTela("MCP23X17 nao mandatorio, continuando o fluxo...");
}
}
else {
PrintTela("MCP23X17 iniciado com sucesso!");
mcpInicializado = true;
}
}
}
void iniciarADS(T_Code Modulo, String Mod_ID, int sda, int scl, byte endereco, bool Mandatorio = false) {
PrintTela("Iniciando ADS1115...");
if (!adsInicializado) {
bool init = Wire.begin(sda, scl);
String str = "SDA " + (String)sda + " SCL " + (String)scl + " Res " + init + " - ";
PrintTela(str, false);
if (!ads.begin(endereco, &Wire)) {
adsInicializado = false;
PrintTela("Erro ao iniciar ADS1115!");
if (Mandatorio) {
PrintTela("Conexão obrigatória, tentando novamente em 5 segundos...");
//EnviarDadosSerial(Mod_ID, MontarProtocoloErro(Modulo));
delay(5000);
iniciarADS(Modulo, Mod_ID, sda, scl, endereco, Mandatorio);
}
else {
PrintTela("ADS1115 nao mandatorio, continuando o fluxo...");
}
}
else {
ads.setGain(GAIN_ONE);
PrintTela("ADS1115 iniciado com sucesso!");
adsInicializado = true;
}
}
}
#endif #endif

View File

@ -2,9 +2,8 @@
#define SensorCorrenteModel #define SensorCorrenteModel
#include "SerialService.h" #include "SerialService.h"
#include "Pinout.h" #include "I2CService.h"
#include "Utils.h" #include "Utils.h"
#include "MuxService.h"
#include <Wire.h> #include <Wire.h>
#include <vector> #include <vector>
#include <Adafruit_INA219.h> #include <Adafruit_INA219.h>
@ -37,19 +36,18 @@ class SensorCorrente {
return; return;
} }
if (!I2CService::SolicitarAcessoI2C(ID_Num, _CanalMUX)) return;
isINA219 = _A_Shunt == TiposShuntCorrente::INA219_3A2; isINA219 = _A_Shunt == TiposShuntCorrente::INA219_3A2;
MuxService::SelecionarCanal(_CanalMUX); bool encontrado = I2CService::VerificaEnderecoBarramento(_Endereco);
if (encontrado) {
Wire.beginTransmission(_Endereco);
byte error = Wire.endTransmission();
if (error == 0) {
if (isINA219) { if (isINA219) {
sINA219 = Adafruit_INA219(_Endereco); sINA219 = Adafruit_INA219(_Endereco);
Iniciado = sINA219.begin(); Iniciado = sINA219.begin();
if (Iniciado) { if (Iniciado) {
sINA219.setCalibration_32V_2A(); sINA219.setCalibration_32V_2A();
PrintTela(_ID + " iniciado"); PrintTela(_ID + " (INA219) iniciado no canal " + String(_CanalMUX));
} }
else { else {
PrintTela(_ID + " nao iniciado!"); PrintTela(_ID + " nao iniciado!");
@ -57,8 +55,6 @@ class SensorCorrente {
} }
else { else {
Iniciado = true; Iniciado = true;
EscreverRegistradorINA(0x00, 0x8000); // Bit 15 = 1 → RESET
delay(2);
switch (_A_Shunt) { switch (_A_Shunt) {
case TiposShuntCorrente::INA228_10A: case TiposShuntCorrente::INA228_10A:
currentLSB = currentLSB_10A; currentLSB = currentLSB_10A;
@ -70,12 +66,17 @@ class SensorCorrente {
currentLSB = currentLSB_100A; currentLSB = currentLSB_100A;
break; break;
} }
PrintTela(_ID + " iniciado"); EscreverRegistradorINA(0x00, 0x8000); // Bit 15 = 1 → RESET
uint16_t cal = (uint16_t)(0.00512 / (currentLSB * shuntLSB));
//EscreverRegistradorINA(0xD4, cal);
PrintTela(_ID + " (INA228) iniciado no canal " + String(_CanalMUX));
} }
} else { } else {
Iniciado = false; Iniciado = false;
PrintTela(_ID + " nao iniciado, endereco " + _Endereco + " nao encontrado!"); PrintTela(_ID + " nao iniciado, endereco " + _Endereco + " nao encontrado!");
} }
I2CService::LiberarAcessoI2C(ID_Num);
} }
void Desligar() { void Desligar() {
@ -85,12 +86,18 @@ class SensorCorrente {
} }
Iniciado = false; Iniciado = false;
if (I2CService::QuemEstaUsando() == ID_Num) {
while (I2CService::QuemEstaUsando() == ID_Num) {
delay(10);
}
}
PrintTela(_ID + " Desligado"); PrintTela(_ID + " Desligado");
} }
void RequisitarDados() { void RequisitarDados() {
if (!Iniciado) return; if (!Iniciado) return;
MuxService::SelecionarCanal(_CanalMUX);
AferirCorrente(); AferirCorrente();
} }
@ -186,29 +193,40 @@ class SensorCorrente {
float currentLSB = 0.0001; float currentLSB = 0.0001;
uint32_t LerRegistradorINA(uint8_t reg, uint8_t bytes) { uint32_t LerRegistradorINA(uint8_t reg, uint8_t bytes) {
Wire.beginTransmission(_Endereco); uint8_t buffer[4] = {0};
Wire.write(reg);
Wire.endTransmission(false); if (bytes > 4) return 0;
Wire.requestFrom(_Endereco, bytes);
// Aumentar timeout para garantir tempo de resposta
if (!I2CService::LeituraSegura(_Endereco, buffer, bytes, reg)) {
Serial.printf("[sCOR] Falha na leitura do registrador 0x%02X\n", reg);
return 0;
}
uint32_t valor = 0; uint32_t valor = 0;
for (uint8_t i = 0; i < bytes; i++) { for (uint8_t i = 0; i < bytes; i++) {
valor = (valor << 8) | Wire.read(); valor = (valor << 8) | buffer[i];
} }
return valor; return valor;
} }
void EscreverRegistradorINA(uint8_t reg, uint16_t valor) { void EscreverRegistradorINA(uint8_t reg, uint16_t valor) {
Wire.beginTransmission(_Endereco); uint8_t dados[3];
Wire.write(reg); dados[0] = reg;
Wire.write((valor >> 8) & 0xFF); // MSB dados[1] = (valor >> 8) & 0xFF;
Wire.write(valor & 0xFF); // LSB dados[2] = valor & 0xFF;
Wire.endTransmission();
if (!I2CService::EscritaSegura(_Endereco, dados, 3, 50)) {
Serial.printf("[INA] Falha ao escrever no registrador 0x%02X\n", reg);
}
} }
void AferirCorrente() { void AferirCorrente() {
if (!Iniciado) return; if (!Iniciado) return;
if (!I2CService::SolicitarAcessoI2C(ID_Num, _CanalMUX)) return;
if (isINA219) { if (isINA219) {
busVoltage = sINA219.getBusVoltage_V(); busVoltage = sINA219.getBusVoltage_V();
current = sINA219.getCurrent_mA() / 10000.0; current = sINA219.getCurrent_mA() / 10000.0;
@ -227,6 +245,8 @@ class SensorCorrente {
energy = rawEnergy * currentLSB * 3.125 * 16 / 3600.0; energy = rawEnergy * currentLSB * 3.125 * 16 / 3600.0;
temperature = ((int16_t)rawTemp) * 0.0078125; temperature = ((int16_t)rawTemp) * 0.0078125;
} }
I2CService::LiberarAcessoI2C(ID_Num);
} }
}; };

View File

@ -1,12 +1,12 @@
#ifndef SensorIMUModel #ifndef SensorIMUModel
#define SensorIMUModel #define SensorIMUModel
#include "SerialService.h"
#include "I2CService.h"
#include <MPU9250_asukiaaa.h> #include <MPU9250_asukiaaa.h>
#include <Adafruit_BMP280.h> #include <Adafruit_BMP280.h>
#include <MadgwickAHRS.h> #include <MahonyAHRS.h>
#include <Wire.h> #include <Wire.h>
#include "SerialService.h"
#include "Pinout.h"
class SensorIMU { class SensorIMU {
public: public:
@ -30,10 +30,9 @@ class SensorIMU {
// BMP280 (Temperatura, Pressão, Altitude) // BMP280 (Temperatura, Pressão, Altitude)
Adafruit_BMP280 bmp; Adafruit_BMP280 bmp;
Madgwick filter; Mahony filter;
float filterHz = 250.0f; int filterHz = 100;
float filterBeta = 0.2f; TickType_t filterDelay = pdMS_TO_TICKS(roundf(1000.0f / filterHz));
int filterDelay = 1000.0f / filterHz;
// Leituras principais // Leituras principais
float AccX = 0, AccY = 0, AccZ = 0; float AccX = 0, AccY = 0, AccZ = 0;
@ -57,24 +56,20 @@ class SensorIMU {
return; return;
} }
Wire.beginTransmission(_EnderecoMPU); if (!I2CService::SolicitarAcessoI2C(ID_Num)) return;
byte errorMpu = Wire.endTransmission();
MpuIniciado = errorMpu == 0; MpuIniciado = I2CService::VerificaEnderecoBarramento(_EnderecoMPU);
if (MpuIniciado) { if (MpuIniciado) {
mpu.setWire(&Wire); mpu.setWire(&Wire);
mpu.beginAccel(); mpu.beginAccel();
mpu.beginGyro(); mpu.beginGyro();
mpu.beginMag(); //mpu.beginMag();
PrintTela("MPU9250 iniciado");
filter.begin(filterHz);
filter.setBeta(filterBeta);
} else { } else {
PrintTela("MPU9250 nao encontrado no endereco " + String(_EnderecoMPU)); PrintTela("MPU9250 nao encontrado no endereco " + String(_EnderecoMPU));
} }
Wire.beginTransmission(_EnderecoBMP); bool BmpEncontrado = I2CService::VerificaEnderecoBarramento(_EnderecoBMP);
byte errorBmp = Wire.endTransmission();
bool BmpEncontrado = errorBmp == 0;
if (BmpEncontrado) { if (BmpEncontrado) {
BmpIniciado = bmp.begin(_EnderecoBMP); BmpIniciado = bmp.begin(_EnderecoBMP);
if (BmpIniciado) { if (BmpIniciado) {
@ -83,6 +78,7 @@ class SensorIMU {
Adafruit_BMP280::SAMPLING_X16, Adafruit_BMP280::SAMPLING_X16,
Adafruit_BMP280::FILTER_X16, Adafruit_BMP280::FILTER_X16,
Adafruit_BMP280::STANDBY_MS_500); Adafruit_BMP280::STANDBY_MS_500);
PrintTela("BMP280 iniciado");
} }
else { else {
PrintTela("Erro ao iniciar BMP280"); PrintTela("Erro ao iniciar BMP280");
@ -94,9 +90,12 @@ class SensorIMU {
Iniciado = MpuIniciado || BmpIniciado; Iniciado = MpuIniciado || BmpIniciado;
if (Iniciado) { if (Iniciado) {
filterDelay = 1000.0f / filterHz;
xTaskCreatePinnedToCore(&SensorIMU::IMUTaskWrapper, "IMUTask", 5000, this, 20, &IMUTaskHandle, tskNO_AFFINITY); xTaskCreatePinnedToCore(&SensorIMU::IMUTaskWrapper, "IMUTask", 5000, this, 20, &IMUTaskHandle, tskNO_AFFINITY);
PrintTela(_ID + " iniciado"); PrintTela(_ID + " iniciado");
} }
I2CService::LiberarAcessoI2C(ID_Num);
} }
void Desligar() { void Desligar() {
@ -105,6 +104,14 @@ class SensorIMU {
return; return;
} }
Iniciado = false;
if (I2CService::QuemEstaUsando() == ID_Num) {
while (I2CService::QuemEstaUsando() == ID_Num) {
delay(10);
}
}
// Parar a execução das tarefas // Parar a execução das tarefas
if (IMUTaskHandle != NULL) { if (IMUTaskHandle != NULL) {
vTaskDelete(IMUTaskHandle); vTaskDelete(IMUTaskHandle);
@ -112,18 +119,10 @@ class SensorIMU {
} }
PrintTela(_ID + " Desligado"); PrintTela(_ID + " Desligado");
Iniciado = false;
} }
void RequisitarDados() { void RequisitarDados() {
/*Serial.print("Temp: "); Serial.println(Temp); AferirDadosTMP();
Serial.print("Pressao: "); Serial.println(Pressao);
Serial.print("Altitude: "); Serial.println(Altitude);
Serial.print("Roll: "); Serial.println(Roll);
Serial.print("Pitch: "); Serial.println(Pitch);
Serial.print("Yaw: "); Serial.println(Yaw);
Serial.println();*/
} }
std::vector<uint8_t> MontarMensagemCAN(CanMessagePosicaoDados posicao) { std::vector<uint8_t> MontarMensagemCAN(CanMessagePosicaoDados posicao) {
@ -206,18 +205,24 @@ class SensorIMU {
} }
void IMUTask() { void IMUTask() {
TickType_t xLastWakeTime = xTaskGetTickCount();
while (1) { while (1) {
if (Iniciado) { if (Iniciado) {
AferirDados(); AferirDadosIMU();
vTaskDelayUntil(&xLastWakeTime, filterDelay);
}
else {
vTaskDelay(1000);
} }
vTaskDelay(pdMS_TO_TICKS(filterDelay));
} }
} }
void AferirDados() { void AferirDadosIMU() {
if (!Iniciado) return; if (!MpuIniciado) return;
if (!I2CService::SolicitarAcessoI2C(ID_Num, -1, 5)) return;
if (MpuIniciado) {
mpu.accelUpdate(); mpu.accelUpdate();
mpu.gyroUpdate(); mpu.gyroUpdate();
mpu.magUpdate(); mpu.magUpdate();
@ -230,16 +235,11 @@ class SensorIMU {
GyroY = mpu.gyroY(); GyroY = mpu.gyroY();
GyroZ = mpu.gyroZ(); GyroZ = mpu.gyroZ();
MagX = mpu.magX(); /*MagX = mpu.magX();
MagY = mpu.magY(); MagY = mpu.magY();
MagZ = mpu.magZ(); MagZ = mpu.magZ();*/
if (true || MagX == 0 && MagY == 0 && MagZ == 0) {
filter.updateIMU(GyroX, GyroY, GyroZ, AccX, AccY, AccZ); filter.updateIMU(GyroX, GyroY, GyroZ, AccX, AccY, AccZ);
}
else {
filter.update(GyroX, GyroY, GyroZ, AccX, AccY, AccZ, MagX, MagY, MagZ);
}
// Recupera os quaternions // Recupera os quaternions
float q0 = filter.getQ0(); float q0 = filter.getQ0();
@ -257,13 +257,20 @@ class SensorIMU {
Roll = (Roll > 0) ? Roll - 180 : Roll + 180; Roll = (Roll > 0) ? Roll - 180 : Roll + 180;
Pitch = -(atan2(-upX, sqrt(upY * upY + upZ * upZ)) * RAD_TO_DEG); Pitch = -(atan2(-upX, sqrt(upY * upY + upZ * upZ)) * RAD_TO_DEG);
Yaw = atan2(2.0f * (q1 * q2 + q0 * q3), q0*q0 + q1*q1 - q2*q2 - q3*q3) * RAD_TO_DEG; Yaw = atan2(2.0f * (q1 * q2 + q0 * q3), q0*q0 + q1*q1 - q2*q2 - q3*q3) * RAD_TO_DEG;
I2CService::LiberarAcessoI2C(ID_Num);
} }
if (BmpIniciado) { void AferirDadosTMP() {
if (!BmpIniciado) return;
if (!I2CService::SolicitarAcessoI2C(ID_Num)) return;
Temp = bmp.readTemperature(); Temp = bmp.readTemperature();
Pressao = bmp.readPressure(); Pressao = bmp.readPressure();
Altitude = bmp.readAltitude(); Altitude = bmp.readAltitude();
}
I2CService::LiberarAcessoI2C(ID_Num);
} }
}; };

View File

@ -6,7 +6,7 @@
#include "C:\ZendionInc\agrobot_base\Firmware\Modulos\SerialService.h" #include "C:\ZendionInc\agrobot_base\Firmware\Modulos\SerialService.h"
#include "C:\ZendionInc\agrobot_base\Firmware\Modulos\CanService.h" #include "C:\ZendionInc\agrobot_base\Firmware\Modulos\CanService.h"
#include "C:\ZendionInc\agrobot_base\Firmware\Modulos\EepromService.h" #include "C:\ZendionInc\agrobot_base\Firmware\Modulos\EepromService.h"
#include "C:\ZendionInc\agrobot_base\Firmware\Modulos\MuxService.h" #include "C:\ZendionInc\agrobot_base\Firmware\Modulos\I2CService.h"
#include "C:\ZendionInc\agrobot_base\Firmware\Modulos\Utils.h" #include "C:\ZendionInc\agrobot_base\Firmware\Modulos\Utils.h"
#include "C:\ZendionInc\agrobot_base\Firmware\Modulos\Pinout.h" #include "C:\ZendionInc\agrobot_base\Firmware\Modulos\Pinout.h"
#include "C:\ZendionInc\agrobot_base\Firmware\Modulos\SensorTemperaturaModel.h" #include "C:\ZendionInc\agrobot_base\Firmware\Modulos\SensorTemperaturaModel.h"
@ -37,10 +37,6 @@ int latenciaLoop = 0;
int qtdEnviosStatus = 0; int qtdEnviosStatus = 0;
int maxEnviosStatus = 5; int maxEnviosStatus = 5;
PinoModel _pinoSDA = PinoModel(1, CONTROLADOR, _INPUT);
PinoModel _pinoSCL = PinoModel(2, CONTROLADOR, _INPUT);
std::vector<SensorTemperatura*> listaSensoresTemperatura; std::vector<SensorTemperatura*> listaSensoresTemperatura;
std::vector<SensorCorrente*> listaSensoresCorrente; std::vector<SensorCorrente*> listaSensoresCorrente;
std::vector<Sinaleiro*> listaSinaleiros; std::vector<Sinaleiro*> listaSinaleiros;
@ -48,13 +44,17 @@ std::vector<Rele*> listaReles;
std::vector<ServoFreio*> listaServoFreios; std::vector<ServoFreio*> listaServoFreios;
std::vector<SensorIMU*> listaSensoresIMU; std::vector<SensorIMU*> listaSensoresIMU;
void inicializarDependenciasI2C() {
I2CService::IniciarI2C();
I2CService::IniciarMUX();
I2CService::IniciarMCP();
I2CService::IniciarADS();
}
void setup() { void setup() {
delay(5000); delay(5000);
iniciarMCP(D_Code, Mod_ID, _pinoSDA.num, _pinoSCL.num, 0x20, false); inicializarDependenciasI2C();
iniciarADS(D_Code, Mod_ID, _pinoSDA.num, _pinoSCL.num, 0x48, false);
MuxService::IniciarMUX();
// Registrar callback para processar mensagens CAN recebidas // Registrar callback para processar mensagens CAN recebidas
canService.setReceiveCallback([](int packetSize, int senderId, byte funcCode, byte* data, int dataLength) { canService.setReceiveCallback([](int packetSize, int senderId, byte funcCode, byte* data, int dataLength) {
@ -78,6 +78,7 @@ void loop() {
} }
canService.loop(); canService.loop();
I2CService::VerificarI2CPreso();
delay(1); delay(1);
@ -109,9 +110,11 @@ void enviarDadosSensores() {
if (enviarStatus) { if (enviarStatus) {
EnviarDadosCAN(sensor->MontarMensagemCAN(CanMessagePosicaoDados::Status)); EnviarDadosCAN(sensor->MontarMensagemCAN(CanMessagePosicaoDados::Status));
} }
if (sensor->Iniciado) {
EnviarDadosCAN(sensor->MontarMensagemCAN(CanMessagePosicaoDados::Dados1)); EnviarDadosCAN(sensor->MontarMensagemCAN(CanMessagePosicaoDados::Dados1));
} }
} }
}
for (auto* sensor : listaSensoresCorrente) { for (auto* sensor : listaSensoresCorrente) {
if (sensor != nullptr) { if (sensor != nullptr) {
@ -119,10 +122,12 @@ void enviarDadosSensores() {
if (enviarStatus) { if (enviarStatus) {
EnviarDadosCAN(sensor->MontarMensagemCAN(CanMessagePosicaoDados::Status)); EnviarDadosCAN(sensor->MontarMensagemCAN(CanMessagePosicaoDados::Status));
} }
if (sensor->Iniciado) {
EnviarDadosCAN(sensor->MontarMensagemCAN(CanMessagePosicaoDados::Dados1)); EnviarDadosCAN(sensor->MontarMensagemCAN(CanMessagePosicaoDados::Dados1));
EnviarDadosCAN(sensor->MontarMensagemCAN(CanMessagePosicaoDados::Dados2)); EnviarDadosCAN(sensor->MontarMensagemCAN(CanMessagePosicaoDados::Dados2));
} }
} }
}
for (auto* sensor : listaSinaleiros) { for (auto* sensor : listaSinaleiros) {
if (sensor != nullptr) { if (sensor != nullptr) {
@ -130,9 +135,11 @@ void enviarDadosSensores() {
if (enviarStatus) { if (enviarStatus) {
EnviarDadosCAN(sensor->MontarMensagemCAN(CanMessagePosicaoDados::Status)); EnviarDadosCAN(sensor->MontarMensagemCAN(CanMessagePosicaoDados::Status));
} }
if (sensor->Iniciado) {
EnviarDadosCAN(sensor->MontarMensagemCAN(CanMessagePosicaoDados::Dados1)); EnviarDadosCAN(sensor->MontarMensagemCAN(CanMessagePosicaoDados::Dados1));
} }
} }
}
for (auto* sensor : listaReles) { for (auto* sensor : listaReles) {
if (sensor != nullptr) { if (sensor != nullptr) {
@ -140,9 +147,11 @@ void enviarDadosSensores() {
if (enviarStatus) { if (enviarStatus) {
EnviarDadosCAN(sensor->MontarMensagemCAN(CanMessagePosicaoDados::Status)); EnviarDadosCAN(sensor->MontarMensagemCAN(CanMessagePosicaoDados::Status));
} }
if (sensor->Iniciado) {
EnviarDadosCAN(sensor->MontarMensagemCAN(CanMessagePosicaoDados::Dados1)); EnviarDadosCAN(sensor->MontarMensagemCAN(CanMessagePosicaoDados::Dados1));
} }
} }
}
for (auto* sensor : listaServoFreios) { for (auto* sensor : listaServoFreios) {
if (sensor != nullptr) { if (sensor != nullptr) {
@ -150,9 +159,11 @@ void enviarDadosSensores() {
if (enviarStatus) { if (enviarStatus) {
EnviarDadosCAN(sensor->MontarMensagemCAN(CanMessagePosicaoDados::Status)); EnviarDadosCAN(sensor->MontarMensagemCAN(CanMessagePosicaoDados::Status));
} }
if (sensor->Iniciado) {
EnviarDadosCAN(sensor->MontarMensagemCAN(CanMessagePosicaoDados::Dados1)); EnviarDadosCAN(sensor->MontarMensagemCAN(CanMessagePosicaoDados::Dados1));
} }
} }
}
for (auto* sensor : listaSensoresIMU) { for (auto* sensor : listaSensoresIMU) {
if (sensor != nullptr) { if (sensor != nullptr) {
@ -160,10 +171,14 @@ void enviarDadosSensores() {
if (enviarStatus) { if (enviarStatus) {
EnviarDadosCAN(sensor->MontarMensagemCAN(CanMessagePosicaoDados::Status)); EnviarDadosCAN(sensor->MontarMensagemCAN(CanMessagePosicaoDados::Status));
} }
if (sensor->MpuIniciado) {
EnviarDadosCAN(sensor->MontarMensagemCAN(CanMessagePosicaoDados::Dados1)); EnviarDadosCAN(sensor->MontarMensagemCAN(CanMessagePosicaoDados::Dados1));
}
if (sensor->BmpIniciado) {
EnviarDadosCAN(sensor->MontarMensagemCAN(CanMessagePosicaoDados::Dados2)); EnviarDadosCAN(sensor->MontarMensagemCAN(CanMessagePosicaoDados::Dados2));
} }
} }
}
if (enviarStatus) { if (enviarStatus) {
qtdEnviosStatus = 0; qtdEnviosStatus = 0;
@ -228,13 +243,8 @@ void ProcessarCfg(std::vector<uint8_t> data) {
int pinoSDA = data[4]; int pinoSDA = data[4];
int pinoSCL = data[5]; int pinoSCL = data[5];
if (pinoSDA != PINO_INVALIDO && pinoSCL != PINO_INVALIDO) { if (pinoSDA != PINO_INVALIDO && pinoSCL != PINO_INVALIDO) {
_pinoSDA = PinoModel(pinoSDA, CONTROLADOR, _INPUT); I2CService::DefinirPinos(pinoSDA, pinoSCL);
_pinoSCL = PinoModel(pinoSCL, CONTROLADOR, _INPUT); inicializarDependenciasI2C();
Wire.end();
Wire.begin(_pinoSDA.num, _pinoSCL.num);
PrintTela("[SEN] I2C inicializado nos pinos SDA=" + String(pinoSDA) + " e SCL=" + String(pinoSCL));
MuxService::IniciarMUX();
} }
vTaskDelay(pdMS_TO_TICKS(100)); vTaskDelay(pdMS_TO_TICKS(100));
Conectado = Conectar; Conectado = Conectar;