[Solved] Due + Ethernet Shield + encoder reading

Hello everyone,

I am using Arduino Due to read an encoder and send it through udp using ethernet shield.

I can read the encoder value on the serial monitor by the code below:

#include <Ethernet.h>
#include <EthernetUdp.h>

volatile int64_t AbsPos , AbsPosBase;

// Enter a MAC address and IP address for your controller below.
// The IP address will be dependent on your local network:
byte mac[] = {
  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED
};
IPAddress ip(192, 168, 1, 20);
IPAddress remoteIP(192,168,1,10);
unsigned int localPort = 8888;      // local port to listen on
unsigned int remotePort = 8888;

// buffers for receiving and sending data
char packetBuffer[UDP_TX_PACKET_MAX_SIZE];

EthernetUDP Udp;

void setup() {
  //Ethernet SETUP ------------------------------------------------------------------------------------------------------------------------------
  Ethernet.begin(mac, ip);
  Serial.begin(250000);
  
  // Check for Ethernet hardware present
  if (Ethernet.hardwareStatus() == EthernetNoHardware) {
    Serial.println("Ethernet shield was not found.  Sorry, can't run without hardware. :(");
    while (true) {
      delay(1); // do nothing, no point running without Ethernet hardware
    }
  }
  if (Ethernet.linkStatus() == LinkOFF) {
    Serial.println("Ethernet cable is not connected.");
  }
  
  // start UDP
  Udp.begin(localPort);
  
  //QUAD Encoder SETUP ----------------------------------------------------------------------------------------------------------------------------
  
  PMC->PMC_PCER1 = PMC_PCER1_PID33                  // TC6 power ON ; Timer counter 2 channel 0 is TC6
                   | PMC_PCER1_PID34;               // TC7 power ON ; Timer counter 2 channel 1 is TC7

  // TC6 in capture mode
  TC2->TC_CHANNEL[0].TC_CMR = TC_CMR_TCCLKS_TIMER_CLOCK1   // capture mode, MCK/2, clk on rising edge
                              | TC_CMR_ABETRG              // TIOA6 is used as an external trigger.
                              | TC_CMR_LDRA_EDGE           // RA loading on each edge of TIOA6
                              | TC_CMR_ETRGEDG_RISING;     // External TC trigger by edge selection of TIOA

  TC2->TC_BMR = TC_BMR_QDEN                                // Enable QDEC (filter, edge detection and quadrature decoding)
                | TC_BMR_POSEN                             // Enable the position measure on channel 0
                | TC_BMR_EDGPHA                            // Edges are detected on both PHA and PHB
                // | TC_BMR_SWAP                              // Swap PHA and PHB if necessary
                | TC_BMR_MAXFILT(1);                       // Pulses with a period shorter than MAXFILT+1 peripheral clock cycles are discarded

  TC2->TC_CHANNEL[0].TC_IER = TC_IER_COVFS                 // Interruption enable on TC_CV overflow ( TC_CV = 0xFFFFFFFF)
                              | TC_IER_CPCS;               // Interruption enable on TC_CV underflow ( TC_CV = 0)

  // Enable Compare Fault Channel 0
  TC2->TC_FMR = TC_FMR_ENCF0;                              // To trigger an interrupt whenever TC_CV = TC_RC = 0

  NVIC_EnableIRQ(TC6_IRQn);

  TC2->TC_CHANNEL[0].TC_CCR = TC_CCR_CLKEN | TC_CCR_SWTRG;
  TC2->TC_CHANNEL[1].TC_CCR = TC_CCR_CLKEN | TC_CCR_SWTRG;  
  //-----------------------------------------------------------------------------------------------------------------------------------------------



}

void loop() {
  //READ ENCODERS------------------------------------------------------------------------------------------------------

  //Read output spin quad encoder
  AbsPos = AbsPosBase + (uint32_t)TC2->TC_CHANNEL[0].TC_CV;

  printf("\nthe number: %lld\n", AbsPos);



// Problem occurs when I uncomment here
//  Udp.beginPacket(remoteIP, remotePort);
//  Udp.write('a');
//  Udp.endPacket();
  
  delay(10);
}


void TC6_Handler() {

  uint32_t status = TC2->TC_CHANNEL[0].TC_SR;

  if (status & TC_SR_COVFS) {
    // TC_CV overflow --> TC_CV = 0xFFFFFFFF
    AbsPosBase += 0xFFFFFFFFllu;
  }
  else  { // if (status & TC_SR_CPCS)
    // TC_CV underflow --> TC_CV = 0
    AbsPosBase -= 0xFFFFFFFFllu;
  }
}

The Problem occurs when I uncomment these lines:

//  Udp.beginPacket(remoteIP, remotePort);
//  Udp.write('a');
//  Udp.endPacket();

I can still see the encoder value on serial monitor for once when I rotate the encoder, but it resets immediately for some reason. I think timer counters are reset somehow.

I have also tried to connect ethernet shield with minimum pins ICSP and pin 10 without mounting on top of arduino. Nothing changed. My encoder A and B signals are connected to pin 4 and pin5.

What can be the problem and how can I solve it?

Thank you

What happens if you remove delay() in loop() ?, e.g.:

void loop() {

  static uint32_t Oldmillis;
  const uint32_t Timestamp = 100;


  if ((millis() - Oldmillis) > Timestamp)
  {
    Oldmillis = millis();

    AbsPos = AbsPosBase + (uint32_t)TC2->TC_CHANNEL[0].TC_CV;
    printf( // Print a 64-bit variable
      "%lld\n",
      AbsPos
    );

      Udp.beginPacket(remoteIP, remotePort);
      Udp.write('a');
      Udp.endPacket();
  }
}

Also note that, for QDEC1:

QDEC1:
Timer Counter 2 channel 0 / TIOA and TIOB of channel 0
PHA  TIOA6 = pin 5
PHB  TIOB6 = pin 4
Timer Counter 2 channel 1 / TIOB of channel 1
INDEX  TIOB7 = pin 10

If you have something else than the Encoder Index on pin 10, it resets the counter at each rising edge !

ard_newbie:
What happens if you remove delay() in loop() ?, e.g.:

void loop() {

static uint32_t Oldmillis;
  const uint32_t Timestamp = 100;

if ((millis() - Oldmillis) > Timestamp)
  {
    Oldmillis = millis();

AbsPos = AbsPosBase + (uint32_t)TC2->TC_CHANNEL[0].TC_CV;
    printf( // Print a 64-bit variable
      "%lld\n",
      AbsPos
    );

Udp.beginPacket(remoteIP, remotePort);
      Udp.write('a');
      Udp.endPacket();
  }
}




Also note that, for QDEC1:

QDEC1: 
Timer Counter 2 channel 0 / TIOA and TIOB of channel 0
PHA  TIOA6 = pin 5
PHB  TIOB6 = pin 4
Timer Counter 2 channel 1 / TIOB of channel 1
INDEX  TIOB7 = pin 10

If you have something else than the Encoder Index on pin 10, it resets the counter at each rising edge !

Thank you for your reply. I have checked and delay does not change the result. However, I have ethernet shield connected and it uses pin 10 I guess for SS.

So is there a way to change the pin 10?

You have to change the SS pin in your library.

I have changed the SS pin to 9. Now it works!

For those who wants to change SS pin:

Ethernet.init(9) // will set the SS pin to pin 9.

Note: If you want to mount the shield on top of Arduino, Don't forget to bend the shield's pin 10 and use a jumper between pin 10 and 9 of shield.

Please, can you write the final version of the code