Ir ao conteúdo
  • Cadastre-se

Mario Henrique Luchiari

Membro Júnior
  • Posts

    5
  • Cadastrado em

  • Última visita

  1. Boa tarde, .if e pessoal do clube! Desculpem a minha demora em continuar postando. Estou com uma carga grande de trabalho. A carga ainda está grande mas, reservei um tempinho para dizer que resolvi o problema. Eram os registradores que estavam errados, inclusive o endereço I2C. Isso eu desconfiava desde o começo... Em primeiro lugar o módulo que comprei é uma enganação. Tomem cuidado! Vem apresentado como HMC5883 mas na verdade é QMC5883. A diferença? É brutal! Até o datasheet do QMC é chato de achar. Quando comparar os dois, verá que está tudo diferente. Acertei o endereço e os registradores e pufff! O trem funcionou! Em segundo lugar descobri o endereço na marra. Como? Fiz um programa que testa endereço por endereço até o módulo, que é escravo, responder. Deu certo! Aí que eu fui me tocar que o chip podia ser outro. Pesquisei e descobri que quando o chip tem a inscrição DA5883 é QMC5883 e quando tem L883 é HMC5883L. Vejam nas fotos. Em terceiro, acabei aprendendo muito sobre I2C, a ponto de colocar num osciloscópio para analisar o protocolo! Cheguei à conclusão que, quando o endereço está errado e o chip não responde, a linha do clock que é a amarela só completa a primeira parte (observe que esta possui (quase) três partes sutilmente separadas). Esta primeira parte é o envio do endereço do mestre para o escravo. Quando não obtém resposta do escravo, a sequência termina. A linha azul é a linha de dados, que é o SDA. A sequência desta foto está completa. Ela é de uma comunicação bem sucedida entre mestre e escravo com endereço 0x1A. Quem tiver interesse no código vou postar aqui e considerar esse tópico encerrado! Muito obrigado, .if! você ajudou bastante! Atenção! Este código é para o QMC5883 e não para o HMC5883. /*Apesar de ter requisitado o HMC5883 e na placa do módulo estar escrito isso, o módulo possui o CI QMC5883 cujos endereços de registradores diferem do HMC. Após muita luta e pesquisa, consegui descobrir isso. Este código faz o QMC funcionar de maneira básica, apenas indicando os valores dos eixos X, Y e Z no display LCD 16 x 2 selecionados por um botão no PORTB.F2. A sequência apresenta X, Y, Z e por último a situação de todos os registradores, de 0x00 a 0x0D. Reconheço que consegui com a ajuda, a graça e pela glória de Deus! Versão: e São Carlos, 26 de novembro de 2020. ------------------------------------------------------------------------------*/ //Habilitar as bibliotecas: // I2C, Conversions, C_String e C_Math // RB0 -> SDA e RB1 -> SDL #define QMC5883_ADDRESS 0x1A #define DATA_OUTPUT_REG 0x00 // São de 0x00 a 0x05 #define STATUS_REG 0x06 #define TEMPL_OUTPUT_REG 0x07 #define TEMPH_OUTPUT_REG 0x08 #define CONTROL1_REG 0x09 #define CONTROL2_REG 0x0A #define SETRESET_REG 0x0B #define IDENTIFICATION_REG 0x0D #define botao PORTB.F2 // LCD module connections sbit LCD_RS at RE0_bit; sbit LCD_EN at RE1_bit; sbit LCD_D4 at RD0_bit; sbit LCD_D5 at RD1_bit; sbit LCD_D6 at RD2_bit; sbit LCD_D7 at RD3_bit; sbit LCD_RS_Direction at TRISE0_bit; sbit LCD_EN_Direction at TRISE1_bit; sbit LCD_D4_Direction at TRISD0_bit; sbit LCD_D5_Direction at TRISD1_bit; sbit LCD_D6_Direction at TRISD2_bit; sbit LCD_D7_Direction at TRISD3_bit; // End LCD module connections signed int tmp, tmpx, tmpy, tmpz, tmpr; char tmp1, tmp2, valor, trava, eixo, trava2, hexa; char txt[7], *hexindic = "0x00"; void QMC5883L_Inicio(void){ PORTB.F4 = 1; //Indica entrada no modo inicialização I2C1_Start(); I2C1_Wr( QMC5883_ADDRESS ); I2C1_Wr( CONTROL1_REG ); //I2C1_Wr( 0x1D ); //OSR 512, Scale Range 8 Gauss, ODR 200Hz, Continuous mode I2C1_Wr( 0x0D ); //OSR 512, Scale Range 2 Gauss, ODR 200Hz, Continuous mode I2C1_Stop(); I2C1_Start(); I2C1_Wr( QMC5883_ADDRESS ); I2C1_Wr( CONTROL2_REG ); I2C1_Wr( 0x41 ); I2C1_Stop(); PORTB.F4 = 0; //Indica entrada no modo inicialização } signed int QMC5883_Leitura(void){ PORTB.F5 = 1; //Indica entrada no modo leitura I2C1_Start(); I2C1_Wr( QMC5883_ADDRESS ); if(eixo == 3) I2C1_Wr( valor ); //Ler o valor dos registradores else I2C1_Wr( DATA_OUTPUT_REG ); I2C1_Repeated_Start(); I2C1_Wr( QMC5883_ADDRESS | 1 ); if(eixo == 3) tmpr = I2C1_Rd(0); //Ler o valor dos registradores else{ tmpx = I2C1_Rd(1); tmpx |= I2C1_Rd(1) << 8; tmpy = I2C1_Rd(1); tmpy |= I2C1_Rd(1) << 8; tmpz = I2C1_Rd(1); tmpz |= I2C1_Rd(0) << 8; } I2C1_Stop(); PORTB.F5 = 0; //Indica saída do modo leitura } char hexadec(char hexanum){ if((hexanum >> 4) < 10) hexindic[2] = (hexanum >> 4) +48; else hexindic[2] = (hexanum >> 4) +55; if((hexanum & 0x0F) < 10) hexindic[3] = (hexanum & 0x0F) +48; else hexindic[3] = (hexanum & 0x0F) +55; Lcd_Out_CP(hexindic); //Escreve hexindic depois do texto } void main() { ADCON1 = 0x0F; //desativa o canal analogico CMCON = 7; //desativa os comparadores analogicos TRISB = 0x0F; PORTB = 0x00; valor = 0; trava = 0; eixo = 0; trava2 = 0; //RBPU_bit = 0; Lcd_Init(); //inicia o display Lcd_Cmd(_LCD_CLEAR); //Limpa a tela do LCD Lcd_Cmd(_LCD_CURSOR_OFF); //Desliga o cursor piscante Delay_ms(100); Lcd_Out(1,1,"QMC5883e-Simples"); Delay_ms(500); I2C1_Init(100000); //Inicializa comunicação I2C Delay_ms(50); QMC5883L_Inicio(); //Inicializa o módulo QMC5883. Engraçado que sem... Delay_ms(50); //... inicializar pela segunda vez, às vezes falha! QMC5883L_Inicio(); //Inicializa o módulo QMC5883 novamente !!! while(1) { QMC5883_Leitura(); //Lê o módulo if(!eixo){ if(trava2){ Lcd_Out(1,1,"QMC5883e-Simples"); Lcd_Out(2,1," "); } Lcd_Out(2,5,"X:"); IntToStr(tmpx, txt); Lcd_Out_CP(txt); valor = 0; trava2 = 0; } if(eixo == 1){ Lcd_Out(2,5,"Y:"); IntToStr(tmpy, txt); Lcd_Out_CP(txt); } if(eixo == 2){ Lcd_Out(2,5,"Z:"); IntToStr(tmpz, txt); Lcd_Out_CP(txt); } if(eixo == 3){ if(!trava2) Lcd_Cmd(_LCD_CLEAR); trava2 = 1; Lcd_Out(1,3,"Reg: "); hexadec(valor); Lcd_Out(2,3,"Valor: "); hexadec(tmpr); valor++; if(valor > 0x0D) valor = 0; Delay_ms(1000); } Delay_ms(500); if(!botao && !trava){ trava = 1; eixo++; if(eixo > 3) eixo = 0; } if(botao) trava = 0; } }
  2. Boa noite .if! Obrigado por suas considerações. Vamos lá... Vou postar aqui o sketch do Arduino que funciona para darmos uma olhada. Já fiz a sequência de acionamento dos registradores conforme está nela, na esperança que desse resultado. Não funcionou. É a pasta Teste_Mhl.zip em anexo. Você tem razão, ainda não enviei para o LCD na função secundária HMC5883_Leitura(), seria o próximo passo se ela não travasse naquele comando de leitura. Sim a sequência de comandos está coerente com o datasheet e com vários outros programas que encontrei nos sites, embora nenhum deles tenha funcionado. Tenho dúvidas sobre esta sequência e sobre a sequência de inicialização. Porém, estas estão iguais às que tenho visto em outros exemplos. Estou encanado com estas sequências desde o começo... Este é o código do CCS que eu estou debatendo há dias. O original envia dados pela UART, adaptei este para escrever no LCD. Segue anexo o arquivo HMC5883L-Base.zip com o código. Esperava que ele indicasse os valores dos eixos, azimute e tal. Em vez disso, ele sempre dá uma mensagem de que o sensor não foi detectado, como se o sensor não estivesse lá mas, se eu remover o sensor o programa não passa da mensagem "Inicializando...". Acredito que, de alguma forma, o sensor esteja sendo lido. A batalha continua... Um forte abraço, Mario Teste_Mhl.zip HMC5883L-Base.zip
  3. Boa noite .if! Obrigado por retornar. Esse registro 0x03 é o registro de leitura dos eixos. Teoricamente é pra posicionar nele e fazer leituras consecutivas (6) para extrair os 3 eixos (6 bytes). Pegar o MSB, deslocar 8 posições e sobrepor com o LSB. Depois é só tratar isto como uma variável de 16 bits. Já olhei a biblioteca do Arduino e tentei adaptar mas, ainda não tenho conhecimento pra isso, por enquanto... Eu tenho mais experiência com PIC, fico frustrado quando algo funciona no ATMEL e não no PIC. Meu hardware está praticamente pronto, por isso gostaria muito que funcionasse. Repetir o Start é uma dica interessante, já fiz algumas tentativas neste sentido, vou tentar mais. Pode ser que a temporização esteja comprometendo a comunicação I2C e isso dê certo. O interessante é que eu coloco outros módulos como o BMP180, MPU6050 (como já disse) e funciona muito bem... Esse bandido tá me zoando e isso já tá virando ponto de vista e honra!!! Fiz a pesquisa que você citou no post anterior, até encontrei um código do CCS e estava testando até agora, é bem interessante mas ainda não deu resultado. A briga continua... Um forte abraço e mais uma vez, obrigado.
  4. Olá meu caro .if! Já "googlei" até cansar... kkkk Está montado. Verifiquei as conexões, resistores pull-up, já coloquei outro módulo (no caso o MPU6050) e o hardware funcionou. Este módulo funciona no Arduino, então o módulo está operacional. Quero fazer funcionar no PIC pois estou montando um veículo autônomo que o utilizaria como referência de direção. Já testei com o Mplab, CCS e nada funcionou. Estou intrigado, quando tento fazer a leitura do registro 0x03 ele trava aí. Coloquei um led que acende na entrada da função de leitura (HMC5883_Leitura()) e apaga na saída, fiz o mesmo na função de inicialização (HMC5883L_Inicio()). O led da inicialização indica que ele entra e sai o da de leitura fica aceso. Quando comento a função I2C1_Rd a função funciona e o led apaga. Estou a pesquisar mas está difícil... Obrigado pela dica e pela atenção. Um grande abraço.
  5. Olá, pessoal! Estou com problemas para conseguir ler os registradores de um módulo bússola eletrônica. Estou usando compilador Mikroc, PIC 18F4550 e o módulo HMC5883L. A comunicação é I2C mas a instrução de leitura I2C1_Rd trava o código. Não consigo descobrir se o módulo está sendo inicializado corretamente ou se apenas não estou conseguindo ler o registrador do módulo. Será que alguém pode me ajudar? Vou postar meu código anexo para darem uma olhada, é só alterar a extensão de .txt para .c. Desde já obrigado! //Habilitar as bibliotecas: // I2C, Conversions, C_String e C_Math // RB0 -> SDA e RB1 -> SDL // LCD module connections sbit LCD_RS at RE0_bit; sbit LCD_EN at RE1_bit; sbit LCD_D4 at RD0_bit; sbit LCD_D5 at RD1_bit; sbit LCD_D6 at RD2_bit; sbit LCD_D7 at RD3_bit; sbit LCD_RS_Direction at TRISE0_bit; sbit LCD_EN_Direction at TRISE1_bit; sbit LCD_D4_Direction at TRISD0_bit; sbit LCD_D5_Direction at TRISD1_bit; sbit LCD_D6_Direction at TRISD2_bit; sbit LCD_D7_Direction at TRISD3_bit; // End LCD module connections signed int tmp; void HMC5883L_Inicio(){ PORTB.F4 = 1; //Indica entrada no modo inicialização I2C1_Start(); I2C1_Wr( 0x3C ); I2C1_Wr( 0x00 ); I2C1_Wr( 32 ); I2C1_Wr( 0x00 ); //Continuo I2C1_Stop(); Delay_ms(500); PORTB.F4 = 0; //Indica saída do modo inicialização Delay_ms(500); PORTB.F4 = 0; } void HMC5883_Leitura(){ PORTB.F5 = 1; //Indica entrada no modo leitura I2C1_Start(); I2C1_Wr( 0x3C ); I2C1_Wr( 0x03 ); I2C1_Repeated_Start(); I2C1_Wr( 0x3D ); tmp = I2C1_Rd(1)<<8 | I2C1_Rd(0); I2C1_Stop(); Delay_ms(500); PORTB.F5 = 0; //Indica saída do modo leitura } void main() { ADCON1 = 0x0F; //desativa o canal analogico CMCON = 7; //desativa os comparadores analogicos Lcd_Init(); //inicia o display Lcd_Cmd(_LCD_CLEAR); //Limpa a tela do LCD Lcd_Cmd(_LCD_CURSOR_OFF); //Desliga o cursor piscante Lcd_Out(1,1,"HMC5883L-Simples"); TRISB.F4 = 0; TRISB.F5 = 0; TRISB.F6 = 0; TRISB.F7 = 0; Delay_ms(500); I2C1_Init(100000); //Inicializa o módulo I2C PORTB.F4 = 0; PORTB.F5 = 0; PORTB.F6 = 0; PORTB.F7 = 0; Delay_ms(50); HMC5883L_Inicio(); //Inicializa o módulo HMC5883 while(1) { HMC5883_Leitura(); //Lê o módulo Delay_ms(500); } } Mario hmc5883-Simples.txt

Sobre o Clube do Hardware

No ar desde 1996, o Clube do Hardware é uma das maiores, mais antigas e mais respeitadas comunidades sobre tecnologia do Brasil. Leia mais

Direitos autorais

Não permitimos a cópia ou reprodução do conteúdo do nosso site, fórum, newsletters e redes sociais, mesmo citando-se a fonte. Leia mais

×
×
  • Criar novo...