0
\$\begingroup\$

So, my friend stumbled across this old article: https://steemit.com/electronics/@gleb-jeglov/how-to-make-a-vfd-clock-step-by-step He gave me couple IV-18 tubes and asked me if I can make similar clocks. I analysed schematics and came to conclusion that it will be easy project. Way to go, man... Way to go... I made single-side PCB for it. Used mostly SMD components and some additional wires to hook everything on board together. The sketch is old. It requires two ways to implement it:

  1. Rewrite it with modern Arduino IDE. I'm not an experienced coder, so i took second route.
  2. Compile it with Arduino 0023 IDE or older. Worked like charm.

I found compiled HEX file and flashed it with Atmel Studio 7.0 via good old AVRISP Mk.2 clone. The sketch can be found right here: https://www.dropbox.com/sh/akxlkw8z1efvbx8/AACjTD3xdoW5w84w3MEyjpY3a?dl

The clocks basicaly work, but with one exception. I used much simplier encoder for this project. This one: https://lcsc.com/product-detail/Multi-Directional-Switches_Korean-Hroparts-Elec-K1-1502SA-01_C145915.html/en

Basicaly, it's just three buttons stapled together. You can push two buttons sideways and push down the third one. Mechanicaly it's impossible to push any buttons together. So it can be used for menu navigation: next, prev and select or something like that. But I'm not very good at AVR/Arduino coding and can't correctly use it. I managed to make it work somehow - push-button and "next" work good. "prev" works in 1 attempt from 5 or so. Sometimes it doesn't work at all.

Old encoder interrupt function looks like this:

ISR(TIMER1_OVF_vect) {
  TCNT1 = 0xffff - 16000;
  millisecond++;
  if (encoder_debounce >= 0) {
    encoder_debounce--;
  }
  if (encoder_debounce == 0) {
    int encoder_a = (ENC_A_PIN & _BV(ENC_A));
    int encoder_b = (ENC_B_PIN & _BV(ENC_B));
    int encoder_sw = (ENC_SW_PIN & _BV(ENC_SW));
    if (!encoder_sw) {
      encoder_pressed++;
    }
    if (!encoder_a) {
      encoder_pos += encoder_b ? -1 : +1;
    }
    PCIFR |= _BV(PCIF2);
    PCICR |= _BV(PCIE2);
  }
  vfd_refresh();
}

As far as I can understand, it counts encoder impulses and implements debounce.

What i did:

  1. I rewrote encoder interrupt function like this
ISR(TIMER1_OVF_vect) {
  TCNT1 = 0xffff - 16000;
  millisecond++;
  if (encoder_debounce >= 0) {
    encoder_debounce--;
  }
  if (encoder_debounce == 0) {
    int encoder_a = (ENC_A_PIN & _BV(ENC_A));
    int encoder_b = (ENC_B_PIN & _BV(ENC_B));
    int encoder_sw = (ENC_SW_PIN & _BV(ENC_SW));
     if (!encoder_sw) {
     encoder_pressed++;
     }
     if (!encoder_a) {
     encoder_pos ++;
     }
     if (!encoder_b) {
     encoder_pos --;
     }
     PCIFR |= _BV(PCIF2);
     PCICR |= _BV(PCIE2);
  }
  vfd_refresh();
}

I made it to just increment or decrement encoder_pos variable when 'next' (encoder_a) or 'prev' (encoder_b) button gets low. Just like it was for encoder_sw variable (push-button, 'select'). As I said before, 'next' and 'select' work fine. 'prev' works bad or doesn't work at all.

  1. I thought 'Maybee my atmega is bad? Maybee port D7 is half-dead?' I changed port for 'prev' button. Hooked it up to port D0. It didn't help. Then I hooked it to free C2 port - no changes either. Everything works, but 'prev' button. I checked debounce capacitors - they are fine. I switched 'prev' and 'next' places - didn't help. So it must be code issue.

  2. I remembered that in some cases Case Switch is faster and better than If-else and wrote this construction:

ISR(TIMER1_OVF_vect) {
  TCNT1 = 0xffff - 16000;
  millisecond++;
  if (encoder_debounce >= 0) {
    encoder_debounce--;
  }
  if (encoder_debounce == 0) {
    int encoder_a = (ENC_A_PIN & _BV(ENC_A));
    int encoder_b = (ENC_B_PIN & _BV(ENC_B));
    int encoder_sw = (ENC_SW_PIN & _BV(ENC_SW));
    int enc_state = (!encoder_sw)*100 + (!encoder_a)*10 + (!encoder_b);

    switch (enc_state) {
    case 100:
      encoder_pressed++;
      break;
    case 10:
      encoder_pos ++;
      break;
    case 1:
      encoder_pos --;
      break;
    }
    PCIFR |= _BV(PCIF2);
    PCICR |= _BV(PCIE2);
  }
  vfd_refresh();
}

Looks a bit ugly. Works the same way. Nothing changend.

So I don't know how to fix this problem. Any ideas? Why encoder_pos ++; works all the time and encoder_pos --; doesn't work good at all? Thank you in advance.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.