Monday, March 21, 2016

Wiznet W5500 returns 255.255.255.255 on Ethernet.localIP(); call

I spent a good day trying to figure out why my W5500 Ethernet module would not work on my Arduino.

W5500 on Arduino

Voltage Divider


I had used a bread board shield to configure a wireless module before and that worked fine.

Then I used the same shield to drive the W5500. The wireless module was driven by a voltage divider to drop the levels suitable for it. The value for R1 was 10K and R2 was 15K.   The module plugs in a socket and next to socket are posts. I used the posts to wire up the Ethernet module.

Using a logic analyser, everything seemed fine, and later I found out it was because I connected the analyser to the 5V side and not the voltage divided side. 

Out of desperation I read the data sheet for the W5500, I knew it ran on 3.3V and that is why I used the divider, but I found out that it could tolerate 5V levels. So I wired it up directly and it worked!!

It appears that the divider did not provide enough current to drive the W5500. You can use level shifters , maybe a lower resistance divider, or directly drive with 5V.

Hope this can save time for somebody else.

Tuesday, July 15, 2014

Interfacing A Rotary Incremental Encoder to an Arduino _Part 2

In this part I will discuss the hardware setup to use the rotary encoder.


The above is from the Bourns data sheet for the PEC11R Series - 12 mm Incremental Encoder.

It makes a huge difference, without it you can get too many spurious interrupts.

The filtered circuit used is the one shown above, and the unfiltered circuit uses the pins connected via internal pull up directly to the encoder.


The values 1 and -1 indicate direction, clockwise and counter-counterclockwise. The value of zero indicates an invalid reading. You can clearly see for the same number of pulses generated, the filtered had a lot less invalid results. The benefit is that your micro-controller is not wasting time servicing an interrupt that it does not need to process.

Below is the extract from the main code posted on Interfacing A Rotary Incremental Encoder to an Arduino _Part 1

  prevRot = curRot;
  intOccured=true;
}
void loop(){ //Do stuff here }
  // my main code actually checks every 20 msec, so that 
  // is why i have this delay
  delay(20);
  if (intOccured){
    Serial.println ( positionTrack[positionIndex] );
    intOccured=false;
  }
 

Monday, July 14, 2014

Interfacing A Rotary Incremental Encoder to an Arduino _Part 1

I had seen some examples for rotary encoders but found the logic hard to understand. So I did my own implementation based on a table. I have seen other people using a similar method, but I think this method is easier to understand.

PrevNext CodeDirectionArray positonCodeDescription
110113CW00Invalid
01004CW1-1CCW
00102CW21CW
101111CW30Invalid
111014CCW41CW
10008CCW50Invalid
00011CCW60Invalid
01117CCW7-1CCW
8-1CCW
90Invalid
100Invalid
111CW
120Invalid
131CW
14-1CCW
150Invalid
In the two tables above you can see the combinations. The green table is the sequence that follows when turning clockwise or counter clockwise. What I did is combine the two and put it in a table.  Each combination is unique. By looking at the code you can determine if the data read is valid or the direction the encoder is going.

There are three main sections.

First is the setup, which defines the pins to use, enable interrupts and initialize  the previous pin state. Next is the interrupt service routine, and then the actual code that will check for the rotation and increment counters if applicable.

Below is an extract from the data sheet for the ATMEGA 1280, 2560 chip:

PCICR – Pin Change Interrupt Control Register

• Bit 1 – PCIE1: Pin Change Interrupt Enable 1
When the PCIE1 bit is set (one) and the I-bit in the Status Register (SREG) is set (one), pin
change interrupt 1 is enabled. Any change on any enabled PCINT15:8 pin will cause an interrupt.
The corresponding interrupt of Pin Change Interrupt Request is executed from the PCI1
Interrupt Vector. PCINT15:8 pins are enabled individually by the PCMSK1 Register.

This is the code that enables interrupts on those pins:

void InitialiseInterrupt(){
  // switch interrupts off while messing with their settings 
  cli();   
  PCICR =0x01;          // Enable PCIE0: interrupt
  PCMSK0 = 0b00110000;  // Only want pins 10 and 11
  sei();  // turn interrupts back on
}

The service routine reads the state of the encoder pins and combines with the previous state to have an index to the array that contained the valid combinations.

Finally the code in the main loop that checks to see if a rotation occurred. Only a valid rotation will cause it to do something. I also have a counter, because in reality each detent positions generates 4 pulses, which can cause the menu to change to rapidly and hard to select.

Below is the full code:

// Code by Manuel Negri
// July 2014
// Released to the public domain! Enjoy!
#define encoder0PinA 10 // INT4  2
#define encoder0PinB 11 //INT5  3

boolean aa=true;
int prevRot =0;
int curRot =0;
int positionIndex =0;
int rotDirection=0;
int menuInc =0;
int menuDec=0;
int menuItem=0;

// keep track of the position, 
//1 is cw , -1 is ccw and 0 is invalid
int positionTrack[16]= {  
  0,-1, 1, 0,1,  0, 0, -1, -1, 0, 0,1,0,  0, -1, 1};

void setup() {

  pinMode(encoder0PinA, INPUT); 
  pinMode(encoder0PinB, INPUT); 
  pinMode(13,OUTPUT);
  
  // we just have to set, cause they are clear to start
  InitialiseInterrupt();

  if (digitalRead(encoder0PinA) == HIGH) { 
    bitSet(prevRot,1);
  }
  if (digitalRead(encoder0PinB) == HIGH) { 
    bitSet(prevRot,0);
  }

  Serial.begin (19200);
  Serial.println ("start");
}
void InitialiseInterrupt(){
  // switch interrupts off while messing with their settings 
  cli();   
  PCICR =0x01;          // Enable PCIE0: interrupt
  PCMSK0 = 0b00110000;  // Only want pins 10 and 11
  sei();  // turn interrupts back on
}

ISR(PCINT0_vect) {   
  // Interrupt service routine. 
  // Every single PCINT0..7 (=ADC0..5) change
  // will generate an interrupt. This will 
  // always call this method
  
  curRot=0;
  if (digitalRead(encoder0PinA) == HIGH) { 
    bitSet(curRot,1);
  }
  if (digitalRead(encoder0PinB) == HIGH) { 
    bitSet(curRot,0);
  }
  // he we combine  the bits for the previous
  // position with the current
  
  // move the prevRot to the upper nibble
  positionIndex = prevRot<<2 | curRot;

  // and depending on the combination , the rotDirection
  // variable will contain which way the encoder turned
  // or if it was an invalid code
  // with invalid combination, we do nothing.
  rotDirection =positionTrack[positionIndex];

  // The current postion now becomes the previous position
  prevRot = curRot;

}
void loop(){ //Do stuff here }
  // my main code actually checks every 20 msec, so that 
  // is why i have this delay
  delay(20);

  if (rotDirection != 0 ) { // only check if a valid direction
    if (rotDirection == 1 ){
      rotDirection=0;  // reset the direction
      menuInc++;
      // menuInc counts how many pulses where generated 
      // in this direction. Basically it is so we dont go
      // to fast when turning the knob.
      // 
      if (menuInc >=4){ 
        if ( menuItem==15) { // I have 16 menu items
          menuItem=0;        // this is to catch the overflow
        }
        else {
          menuItem++;        // no overflow, so increment
        }
        Serial.print  (menuItem);
        Serial.println ("  menu inc ");
        menuInc= 0;          // since we moved a position
        menuDec = 0;         // reset the two counters
      }
    } 
    else {
      rotDirection=0; // reset the direction
      menuDec--;
      // menuDec counts how many pulses where generated 
      // in this direction. Basically it is so we dont go
      // to fast when turning the knob.
      
      if (menuDec <=-4){
        if ( menuItem==0) { // prevent underflow
          menuItem=15;   
        }
        else {
          menuItem--;
        }
        Serial.print  (menuItem);
        Serial.println ("  menu dec ");
        menuInc= 0;          // since we moved a position
        menuDec = 0;         // reset the two counters
      }
    }
  }
}

Wednesday, July 24, 2013

MySQL Copy one column in a table to another column in another table

I had two tables. One had a status field that I wanted in another table.

Below is the diagram showing the two tables:

To get it to copy the data, I just used the command below:

 update tablea  
     inner join  
   tableb ON tablea.Task_id = tableb .Task_id  
 set   
   tablea.status= tableb .status;  

Monday, November 12, 2012

Rounded Corners in Pulsonix PCB CAD Program

Tried to do nice rounded corners but found it hard to find in the documentation.

The way to do it is, click on the corner, then right click and select fillet.

Choose your radius and away you go.


Finished corner: