LusoRobótica - Robótica em Português

Sistemas específicos => Arduino / AVR => Tópico iniciado por: CBX em 11 de Março de 2014, 18:42

Título: ENC28J60 e MFRC522
Enviado por: CBX em 11 de Março de 2014, 18:42
Boas

Estou de volta de um projecto em que tenho de usar um módulo rfid para ler o id de um cartão e envia-lo através de uma rede ethernet, estou a usar como controlador ethernet um enc28j60 e leitor de rfid um módulo com um mfrc522, para testes estou a usar o arduino visto já existirem bibliotecas  :P

Acontece que o código funciona bem separadamente, mas quando o junto apenas o leitor de rfid funciona correctamente, a única coisa que o módulo ethernet faz é responder a pings.

Já varri as datasheets e ambos usam a mesma frequência de clock, o mesmo modo (modo 0) e não existem conflitos nas bibliotecas com pinos, cada um têm o seu /CS. Pelo que percebi o ENC28J60 põe em alta impedância o MOSI e MISO, na datasheet do MFRC522 não encontrei qualquer referência, será esse o problema? A primeira coisa que me ocorreu foi falta de RAM, mas usei uma pequena função para verificar a RAM livre e mesmo com o uso de strings e o buffer do TCP\IP a ocupar 500 bytes ainda têm ~1k livre .

As bibliotecas que estou a usar: https://github.com/jcw/ethercard e https://github.com/miguelbalboa/rfid

O código:

Código: [Seleccione]
#include <SPI.h>
#include <MFRC522.h>
#include <EtherCard.h>

MFRC522 mfrc522(10, 14); // Create MFRC522 instance.

static byte mymac[] = { 0x74,0x69,0x69,0x2D,0x30,0x31 }; // Endereço MAC
static byte myip[] = { 192,168,2,2 }; // Endereço IP
static byte gwip[] = { 192,168,2,1 }; // Endereço GW
static byte hisip[] = { 192,168,2,1 }; // Endereço servidor remoto
char website[] PROGMEM = "192.168.2.1"; // Nome do servidor remoto
byte Ethernet::buffer[500];   // Buffer do TCP/IP
String id, lastId;

void setup()
{
  Serial.begin(57600);
  ether.begin(sizeof Ethernet::buffer, mymac, 8);
  ether.staticSetup(myip, gwip);
  ether.copyIp(ether.hisip, hisip);
  SPI.begin();
  mfrc522.PCD_Init();
}

void loop()
{
  ether.packetLoop(ether.packetReceive());
 
  id = "";
 
  if (mfrc522.PICC_IsNewCardPresent() && mfrc522.PICC_ReadCardSerial())
  {
    for (int i = 0; i < 4; i++)
    {
      if (mfrc522.uid.uidByte[i] < 0x10) //adds a leading zero
        id += "0";
     
      id += String(mfrc522.uid.uidByte[i], HEX);
    }
   
    if (id != lastId)
    {
      Serial.println(id);
      ether.browseUrl(PSTR("/?id="), "card id here", website, reply);
      tone(9, 2300, 500);
      lastId = id;
    }
   
    else
    {
      tone(9, 2300, 100);
      delay(200);
      tone(9, 2300, 100);
    }
   
    mfrc522.PICC_HaltA();
    delay(1000);
  }
}

// Resposta do servidor
static void reply (byte status, word off, word len)
{
  Serial.println((const char*) Ethernet::buffer + off);
}

Outra coisa: estou a guardar o id numa variável string, mas a função para enviar os dados por ethernet só aceita chars, qual é a melhor forma de tratar isso, tendo em conta que estou a comparar o id com o anterior para verificar se o cartão já foi lido?

Obrigado
Título: Re: ENC28J60 e MFRC522
Enviado por: senso em 11 de Março de 2014, 18:49
Strings e arrays de chars são a mesma coisa, a diferença é que tipicamente uma string é terminada com um caracter nulo, aka /0.
Porque é que o pessoal do arduino resolveu re-inventar isto:
http://www.nongnu.org/avr-libc/user-manual/group__avr__string.html (http://www.nongnu.org/avr-libc/user-manual/group__avr__string.html)

Não faço a mais pálida ideia.
Título: Re: ENC28J60 e MFRC522
Enviado por: CBX em 11 de Março de 2014, 20:50
eu sei que strings são arrays de chars, sei que que para a comparação dos arrays posso usar o strcmp() e para copiar o conteúdo de um array para o outro o strcpy(), a minha duvida é como é que lido com os leading zeros uma vez que preciso de trabalhar com valores hexadecimais, com strings basta somar um 0, assim não estou a ver  ???

edit: não consegui resolver o problema na totalidade a trabalhar com arrays de chars e as funções da biblioteca string, voltei a usar strings e simplesmente a converter a string num array e chars para enviar para a função de envio:

Código: [Seleccione]
id.toCharArray(buffer, 9);
ether.browseUrl(PSTR("/?id="), (const char*)buffer, website, reply);

quando reescrever o código em C vou revisitar o problema, mas agora quero é ter isto a funcionar  ;D

voltamos ao problema inicial, as bibliotecas não se darem bem, por onde devo começar?
Título: Re: ENC28J60 e MFRC522
Enviado por: jmiguelff em 12 de Março de 2014, 11:28
CBX eu não conheço essas bibliotecas por isso a minha ajuda não é grande ajuda. :p

Mas quando usas várias bibliotecas deves ter em atenção ao que está por baixo. As bibliotecas podem usar os mesmos recursos com configurações diferentes e portanto em conjunto não funcionam bem.

Título: Re: ENC28J60 e MFRC522
Enviado por: CBX em 12 de Março de 2014, 16:38
eu sei disso, por essa mesma razão é que a não funciona está por baixo, até já no próprio setup() acrescentei SPI.setClockDivider(SPI_CLOCK_DIV2), SPI.setDataMode(SPI_MODE0) e SPI.setBitOrder(SBFIRST), na scketch que têm apenas o código do cliente web funcionou, no que junta os dois acontece o mesmo, apenas o leitor rfid funciona, quer dizer, o modulo ethernet não está "morto" de todo, ao fazer um ping ele responde, simplesmente não envia nada quando deve...
Título: Re: ENC28J60 e MFRC522
Enviado por: CBX em 15 de Março de 2014, 23:09
Liguei o logic analyzer e ambos os IC's parecem apenas enviar e receber informação quando o o seu CS está low, não sei mais por onde pegar nisto  >:(

Título: Re: ENC28J60 e MFRC522
Enviado por: senso em 15 de Março de 2014, 23:54
You need to go deeper..
Olhar para as bibliotecas e ver que recursos usam.
Título: Re: ENC28J60 e MFRC522
Enviado por: metRo_ em 16 de Março de 2014, 01:13
quando dizes que ele responde ao ping, é o processador que trata esse pedido ou é o controlador ethernet que já tem a camada responsável por esse tipo de pedidos?
Título: Re: ENC28J60 e MFRC522
Enviado por: CBX em 16 de Março de 2014, 02:04
é o mcu, mais propriamente estas duas funções: ether.packetLoop(ether.packetReceive());
Título: Re: ENC28J60 e MFRC522
Enviado por: metRo_ em 16 de Março de 2014, 09:56
é o mcu, mais propriamente estas duas funções: ether.packetLoop(ether.packetReceive());

a minha questão era para tentar perceber se o problema estaria na comunicação por SPI mas aparentemente não. Eu já tive um problema do genero mas era porque um dos integrados mantinha os sinais do SPI num estado que não permitia partilhar o SPI, mas já não me recordo quias eram os integrados.
Título: Re: ENC28J60 e MFRC522
Enviado por: CBX em 16 de Março de 2014, 13:45
Também pensei o mesmo,  mas como responde aos pings o problema está mesmo numa das bibliotecas, suspeito na do mfrc522 uma vez que a ethercard funciona sem problemas com outros spi slaves, por exemplo cartões SD

Fiz um pequeno teste, comentei tudo o que tivesse a haver com a biblioteca mfrc522 e fui descomentando uma função de cada vez, o problema parece estar numa destas, mfrc522.PICC_IsNewCardPresent() ou mfrc522.PICC_ReadCardSerial(), mas o código parece bastante inofensivo, a primeira envia um comando que pergunta se existe um novo cartão presente, a segunda lê o conteúdo do cartão, a segunda está dependente do que a primeira retorna, verdadeiro ou falso.

Vou ter de reler a biblioteca com mais atenção...
Título: Re: ENC28J60 e MFRC522
Enviado por: CBX em 19 de Março de 2014, 19:14
Bem, li a biblioteca toda mais do que uma vez e não encontrei nada que pudesse causar mau funcionamento no bus, liguei o logic analyzer e também não encontrei nada de anormal, testei outra biblioteca e acontece exactamente o mesmo, consigo pingar o módulo a partir da linha de comandos, mas não envia mais nada, sem ser as respostas dos ecos, foi então que me lembrei, será um problema de timings?

Uma vez que ambos os chips usam o mesmo bus spi, logo o mesmo buffer, será que como o programa está constantemente a procurar tags rfid novas está sempre a ocupar o buffer com a sua informação e os dados referentes ao módulo ethernet nunca chegam a ser enviados?

Será que um rtos simples me resolve o problema?

O módulo do MRFC522 por acaso (ou não) até tem um pino IRQ, mas não sei se me vai resolver o problema, estas são as interrupções que podem ser configuradas:

IRq - timer unit - the timer counts from 1 to 0
TxIRq – transmitter - a transmitted data stream ends
CRCIRq - CRC coprocessor - all data from the FIFO buffer has been processed
RxIRq – receiver - a received data stream ends
IdleIRq - ComIrqReg register - command execution finishes
HiAlertIRq - FIFO buffer - the FIFO buffer is almost full
LoAlertIRq - FIFO buffer - the FIFO buffer is almost empty
ErrIRq - contactless UART - an error is detected

Que vos parece?

edit: parece que o SPI não tem nenhum buffer :o
Título: Re: ENC28J60 e MFRC522
Enviado por: zedlav em 19 de Março de 2014, 22:20
Boas.
Se tiveres o servidor no teu pc podes usar o wireshark http://www.wireshark.org/ (http://www.wireshark.org/) para veres o que está acontecer na comunicação.



 
Título: Re: ENC28J60 e MFRC522
Enviado por: CBX em 20 de Março de 2014, 00:12
eu sei, é o que tenho estado a usar...
Título: Re: ENC28J60 e MFRC522
Enviado por: zedlav em 20 de Março de 2014, 09:19
O ENC28J60 chega a enviar o SYN para o servidor?
Título: Re: ENC28J60 e MFRC522
Enviado por: CBX em 20 de Março de 2014, 13:25
Não, apenas respostas aos pings
Título: Re: ENC28J60 e MFRC522
Enviado por: Njay em 20 de Março de 2014, 14:45
Podes estar a ter um problema de stack. O stack começa no final da RAM "utilizável" e cresce para baixo. As variáveis estáticas estão armazenadas no inicio da RAM. Eventualmente o crescimento do stack pode corromper as variáveis estáticas. Acho que podes dizer ao GCC para ligar um "stack checker", mas com o ambiente de Arduino não sei se te safas ;P . Tenta eliminar ou encolher o tamanho de variáveis estáticas, evitar chamadas eliminando funções e metendo o código inline em vez da chamada, reduzir ou eliminar o número de parametros de funções, encolher ou eliminar variáveis locais, ...
Título: Re: ENC28J60 e MFRC522
Enviado por: CBX em 20 de Março de 2014, 19:47
usei esta função para verificar a RAM livre:

Código: [Seleccione]
int freeRam () {
  extern int __heap_start, *__brkval;
  int v;
  return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval);
}

estão 1210 bytes livres

Já tentei diminuir o tamanho do buffer do TCP para metade, mas não adiantou em nada, começo a ficar frustrado com isto  :(
Título: Re: ENC28J60 e MFRC522
Enviado por: zedlav em 20 de Março de 2014, 20:16
Testa com este. Eu não tenho maneira de testar.

Código: [Seleccione]
#include <SPI.h>
#include <MFRC522.h>
#include <EtherCard.h>

MFRC522 mfrc522(10, 14); // Create MFRC522 instance.

static byte mymac[] = { 0x74,0x69,0x69,0x2D,0x30,0x31 }; // Endereço MAC
static byte myip[] = { 192,168,2,2 }; // Endereço IP
static byte gwip[] = { 192,168,2,1 }; // Endereço GW
static byte hisip[] = { 192,168,2,1 }; // Endereço servidor remoto
char website[] PROGMEM = "192.168.2.1"; // Nome do servidor remoto
byte Ethernet::buffer[500];   // Buffer do TCP/IP
String id, lastId;

unsigned char end_tcp_resp = 0;
static uint32_t timer;


void setup()
{
  Serial.begin(57600);
  ether.begin(sizeof Ethernet::buffer, mymac, 8);
  ether.staticSetup(myip, gwip);
  ether.copyIp(ether.hisip, hisip);
  SPI.begin();
  mfrc522.PCD_Init();
}

void loop()
{
 
  ether.packetLoop(ether.packetReceive());
 
  id = "";
 
 
 
  if (mfrc522.PICC_IsNewCardPresent() && mfrc522.PICC_ReadCardSerial() && end_tcp_resp == 0){
    for (int i = 0; i < 4; i++)
    {
     
      if (mfrc522.uid.uidByte[i] < 0x10) //adds a leading zero
        id += "0";
     
      id += String(mfrc522.uid.uidByte[i], HEX);
     
    }
   
 
    mfrc522.PICC_HaltA();
    delay(1000);
  }
 
 
   if (id != lastId && end_tcp_resp == 0){
     
     
        end_tcp_resp = 1;
        Serial.println(id);
        ether.browseUrl(PSTR("/?id="), id, website, reply);
        //tone(9, 2300, 500);
        lastId = id;
timer = millis() + 5000;


   }else{
   
     
        if (millis() > timer && end_tcp_resp == 1) {

     // SE entrar aqui é porque não recebemos resposta do servidor
     // por isso voltamos a por end_tcp_resp a zero
     end_tcp_resp = 0;
 
}

     /*
        tone(9, 2300, 100);
        delay(200);
        tone(9, 2300, 100);
      */
     
   }
 
 
}

// Resposta do servidor
static void reply (byte status, word off, word len)
{
  end_tcp_resp = 0;
  Serial.println((const char*) Ethernet::buffer + off);
}
Título: Re: ENC28J60 e MFRC522
Enviado por: CBX em 20 de Março de 2014, 20:33
não funciona, mesmo problema, vou procurar outra biblioteca para o enc28j60 não vá o problema ser daí...
Título: Re: ENC28J60 e MFRC522
Enviado por: senso em 20 de Março de 2014, 20:44
Presumo que isso seja só o uso de ram em compile time, porque não estou ai a ver nada que coloque um padrão(tipo AA ou 55) na ram toda e que depois vá ver até onde é que encontra esse padrão, essa seria a maneira de saber realmente a ram usada, porque tudo quanto é strings/arrays e afins são passados da flash para a ram durante a execução.
Título: Re: ENC28J60 e MFRC522
Enviado por: LoneWolf em 20 de Março de 2014, 20:59
boas,

Citar
vou procurar outra biblioteca para o enc28j60 não vá o problema ser daí...

... é que é mesmo dai, ando a tentar fazer uma coisa deste  género e algumas bibliotecas não funcionam correctamente e ao add mais bibliotecas os problemas aumentam.

tenta uma dessas duas em anexo ( a mim so deixa fazer alguma coisa se usar a lib enc28j60)

Abraço.
Título: Re: ENC28J60 e MFRC522
Enviado por: zedlav em 20 de Março de 2014, 21:02
Em ultimo caso comunica com a pessoa que fez a lib para o enc28j60 ele melhor do que ninguém poderá respoder qual é o problema.
Título: Re: ENC28J60 e MFRC522
Enviado por: CBX em 20 de Março de 2014, 23:40
boas,

Citar
vou procurar outra biblioteca para o enc28j60 não vá o problema ser daí...

... é que é mesmo dai, ando a tentar fazer uma coisa deste  género e algumas bibliotecas não funcionam correctamente e ao add mais bibliotecas os problemas aumentam.

tenta uma dessas duas em anexo ( a mim so deixa fazer alguma coisa se usar a lib enc28j60)

Abraço.

a enc28j60 está bastante desactualizada, tentei usar a versão mais recente, mas sem sucesso, a ethercard é a que estou a usar, tentei também usar a arduino_uip também sem sucesso...

obrigado
Título: Re: ENC28J60 e MFRC522
Enviado por: LoneWolf em 21 de Março de 2014, 10:32
Boas,

Citar
a enc28j60 está bastante desactualizada,

Obrigado pelo alerta, eu já nao toco nesse projecto a algum tempo assim que voltar a ele vou tentar usar a mais recente a ver se tem melhoras

Abraço.
Título: Re: ENC28J60 e MFRC522
Enviado por: senso em 21 de Março de 2014, 11:20
Possivelmente maior parte do pessoal agora prefere usar os chips da Wiznet, tem muito mais coisas implementadas em hardware.
Título: Re: ENC28J60 e MFRC522
Enviado por: CBX em 21 de Março de 2014, 17:23
é verdade, mas para a maior parte das aplicações o enc28j60 é mais do que suficiente, é menos de metade do preço e tem samples grátis  :P

em relação às bibliotecas, testei quatro, ethercard, ethershield, enc28j60 e arduino_uip, a única que com que consegui transmitir alguma coisa foi com a ehtercard e em termos de recursos penso que seja a mais bem optimizada, foi escrita de raiz, ao contrario da arduino_uip que é um port para arduino, as outras duas estão obsoletas.

Vou tentar por alguma das outras a funcionar para ter a certeza de que o problema é da biblioteca da ethernet, visto já ter testado outra para o mofulo rfid e o problema manter-se...

edit: consegui por a biblioteca arduino_uip a funcionar, assim que adiciono o código do leitor rfid deixa de funcionar, definitivamente o problema está na biblioteca do mfrc522, de volta a mergulhar no código da biblioteca  ::)

edit: finalmente luz ao fundo do túnel, continuei a insistir com a biblioteca arduino_uip e lembrei-me de adicionar um delay de 100ms, só porque sim, na linha seguinte à ultima chamada a uma função da biblioteca MFRC522 e não é que funcionou  :o

2 semanas a bater com a cabeça na parede por causa de um simples delay de 100ms...

(https://lusorobotica.com/proxy.php?request=http%3A%2F%2Fwww.tapped-out.co.uk%2Ffile%2Fattachment%2F2013%2F08%2F483d820019adf64372393c094c7e3d52_view.png&hash=e40cf71e69545522919aeb71719d44b4398a0d12)

esta biblioteca torna o código 10k maior, mas pelo menos funciona
Título: Re: ENC28J60 e MFRC522
Enviado por: senso em 21 de Março de 2014, 22:20
10K de flash?  :o
Título: Re: ENC28J60 e MFRC522
Enviado por: CBX em 21 de Março de 2014, 22:43
parece que a biblioteca implementa TCP, UDP, IP, ARP, ICMP e mais uns quantos protocolos daí o seu tamanho