Problem with 7-Segments and Rotary Encoder

Hi there,

I posted my problem already in the german part of the forum, but until now nobody could help me.

I connected two 7-Segment LED-Displays via two 74HTC595 shift-registers with my arduino, which shall change from 01-40 when I turn around a rotary encoder. (This is at least the step goal - later the final programm shall control the PLL of a radio).

This is the code I used:

#include <PinChangeInt.h> // necessary otherwise we get undefined reference errors.
#include <AdaEncoder.h>

#define a_PINA 5
#define a_PINB 7

const int latch = 8;
const int data = 11;
const int clock = 12;

int kanaele_einer[] =  {6,91,79,102,109,125,7,127,103,63,6,91,79,102,109,125,7,127,103,63,6,91,79,102,109,125,7,127,103,63,6,91,79,102,109,125,7,127,103,63}; // right segment, one-spot? 
int kanaele_zehner[] = {63,63,63,63,63,63,63,63,63,6,6,6,6,6,6,6,6,6,6,91,91,91,91,91,91,91,91,91,91,79,79,79,79,79,79,79,79,79,79,102}; // left segment, ten-spot?
int x = 1;
int8_t clicks=0;
char id=0;

void setup()
{
  AdaEncoder::addEncoder('a', a_PINA, a_PINB);
  pinMode(clock, OUTPUT); // make the clock pin an output
  pinMode(data, OUTPUT); // make the data pin an output
  pinMode(latch, OUTPUT); // make the latch pin an output

}

void loop()
{
  encoder *thisEncoder;
  thisEncoder=AdaEncoder::genie(&clicks, &id);
  if (thisEncoder != NULL) {
    thisEncoder=AdaEncoder::getFirstEncoder();
    
    
    if (clicks > 0 ) {
      x++};
      
      if (x==41) {
        x=1}
    
    if (clicks < 0) {
       x--};
       
        if (x==0) {
        x=40};
    }
       
   // Anzeigenausgabe   
      digitalWrite(latch, 0);
      shiftOut(data, clock, MSBFIRST, kanaele_einer[x]);
      shiftOut(data, clock, MSBFIRST, kanaele_zehner[x]);
      digitalWrite(latch, 1);
    
  
}

My problem is now that the left segment (which shows the tenner) works perfectly (it shows 0-4), however on the right display all segments seem to shine all at once (however in different grades of brightness). There is of a course a slight change if I turn the encoder, but the right segments stay unreadable.

It is not a mistake in the wiring - if I call the 40 different variables up with a for-loop, it works spendlidly. Just how the rotary encoder code works without a problem, if the result is sent via usb to the arduino-gui?

Can anybody help me?

Simplify and tst each component in isolation. Write a simple loop to display a count and see if that works.

AWOL: Simplify and tst each component in isolation. Write a simple loop to display a count and see if that works.

Chimaera: If I call the 40 different variables up with a for-loop, it works spendlidly. Just how the rotary encoder code works without a problem, if the result is sent via usb to the arduino-gui

I already did. This is the strange thing. Both programs run as stand-alone-code perfectly. I think the encoder software somehow influences the shiftregister.

I made the observation, that if test the encoder-code and the 7-segment is still connected (though NOT in the code), some segments start to lighten up, when I rotate the encoder.

I don't fully understand the way you drive the 7seg displays.

I have some experience with 7seg on the PIC.

Usually, I use one table as pattern decoder (0..F, also some extra chars). So I have a number, then I use it as index for the pattern table, and I get the right pattern for the 7seg display.

Then I also use 4x multiplex, all via 74164 or 74595.

For this purpose I use a second table, and usually 8 phases (every second blank) but it also works for 4 phases. This sink drive table really just contains 1110,1101,1011,0111 So one of the multiplexed displays is activated for each phase.

Maybe this is not your problem and your 7seg code somehow works. However, I find it much less intuitive than my solution. I don't know if you can understand PIC 16 C, I have the files online: http://pic.hitechworld.org/716pcb/

And I use inline assembler to shift out the bits, I hope the C source is not too hard to understand.

where you "say" shiftOut, in my source it is called output_byte, and it's hardwired to port bits via defines.

I am interested to start using Atmel chips, for this purpose I read posts here on the forum, and try to understand what is going on in the code.

Really I don't get the logic for kanaele_einer[], and int kanaele_zehner[]

Hi takao,

okay, I explain my system:

It's quite easy. The decimal numbers represent actually the binary number, which sets the output bits of the shift register low and high. The decimal numbers just take less space and make declaring easier.

So the number 6 is actually the binary code 00000110 which makes my segment show the number ONE 91 represents the binary code 1011011 which shows the TWO on the 7-Segment. 79 is as binary number 1001111. The shift register makes with this code a THREE.

In my code so each index number (40 all in all) has a variable for the right ( kanaele_einer = which makes channels_oner in english) and for the left (kanaele_zehner=channels_tenner) display.

int kanaele_einer[] = {6,91,79,102,109,125,7,127,103,63,6,91,79,102,109,125,7,127,103,63,6,91,79,102,109,125,7,127,103,63,6,91,79,102,109,125,7,127,103,63};

int kanaele_zehner[] = {63,63,63,63,63,63,63,63,63,6,6,6,6,6,6,6,6,6,6,91,91,91,91,91,91,91,91,91,91,79,79,79,79,79,79,79,79,79,79,102}; // left segment, ten-spot?

Is it now better to understand?

Well, the problem is this is my first project. And my programming skills are pretty hmm not existent. Thats why i tried to start arduino (and this of course also the reasion why I didn't multiplex at all).

One idea I have is maybe it is required also to declare the encoder pins as inputs.

I entered AdaEncoder::addEncoder in to bing,

http://www.arduino.cc/playground/Main/RotaryEncoders#Example3

and there is such a decleration.

If I have problems with devices worked via shifting registers, I comment out code, and try to track down the problem, for instance tagging a LED+4.7kOhm to the register (just a little solder), and then I try to control this LED individually.

If the inputs decleration is not the cause, I'd try to output the "clicks" variable directly as bitstream.

Declaring the encoder inputs didn't change a thing.

But I guess i'm a little bit further now.

It must be definitly in the code. I thought that in actual fact i could try to understand what happens, if I read it out with the serial output.

Therefore I inserted two extra lines:

 // Anzeigenausgabe   
      digitalWrite(latch, 0);
      shiftOut(data, clock, MSBFIRST, kanaele_einer[x]);
      [color=red]Serial.println(kanaele_einer[x]);[/color]
      shiftOut(data, clock, MSBFIRST, kanaele_zehner[x]);
     [color=red] Serial.println(kanaele_zehner[x]);[/color]
      digitalWrite(latch, 1);
    
  
}

And now the strange thing happens: My serial output nearly oberflows. I get bombed with messages although I do not rotate the encoder at all. It can't be a bouncing problem, as the problem stays if I even remove the encoder from the wiring. It seems as if the program doesnt' stop writing (at the moment 91 and 63) ton the shift register.

Is it possible that the program in the way i set it up doesn't wait for a change to write new numbers, but instead rewrites the old ones all the time?

YES.

That was it!

I just needed to move the bracket which ended the if-condition of the rotary-check.

And i even was able to sort out the rest of my mistakes. So - now at least the step goal is reached.