Author Topic: Schmitt Buffer/Trigger with Encoder and buttons - Inverting...  (Read 6487 times)

0 Members and 1 Guest are viewing this topic.

Offline elcrniTopic starter

  • Regular Contributor
  • *
  • Posts: 98
  • Country: at
hi all,

In a middle of a PCB design and wanted to make things proper with my buttons and rotary encoder. So apart from RC filter, i would also like to include Schmitt Triger for a proper signal of the encoder and buttons.
After researching the matter for a bit, i am still a little confused on "inverting" Schmitt Triger.

My schematic looks like this, except i use 10k resistors and 1uF tantalum caps:



So a few questions:

1. I would like to convert (end debounce) signal from encoder and buttons, so i was thinking of getting this one:
74HC14D
However, this one says "inverter", and i am aware that i can also get inverted signal output, but here i need non inverted signal. So the question is, would this one work for my case?
2. If i do have inverted signal, would that mean simply swapping the contacts on the switch to work as non inverting?
3. 74HC14 has 6 IN/OUT pins, can i use 2 pins for encoder and remaining 4 for 4 buttons? All on one IC? Or is it better to separate for whatever reason?
4. I can use 74HC14 for mechanical toggle switches as well? I see no reason why not.

Many thanks in advance,
Alek
 

Offline Zero999

  • Super Contributor
  • ***
  • Posts: 20357
  • Country: gb
  • 0999
Re: Schmitt Buffer/Trigger with Encoder and buttons - Inverting...
« Reply #1 on: March 16, 2021, 12:36:32 pm »
There are non-inverting Schmitt trigger ICs such as the, 74HC2G17 and 74HC7014, or use two 74HC14 in series to get non-inverting.

Is this going to a microcontroller? If so, check it has Schmitt trigger inputs, then you don't need the 74HC14. Another thing to consider is doing the de-bouncing in software, so no additional components are required.
 

Offline elcrniTopic starter

  • Regular Contributor
  • *
  • Posts: 98
  • Country: at
Re: Schmitt Buffer/Trigger with Encoder and buttons - Inverting...
« Reply #2 on: March 16, 2021, 12:51:04 pm »
Thanks Zero999,

Yes, the signal is going to Arduino Mega, i am not sure it has Schmitt input as such.
Also, i would like to avoid software debouncing as my code is decoding radio signals so i would like to keep it as light as possible.

Many thanks,
Alek

P.S. i can use both encoder and switches on the same 74HC14 IC at the same time?
 

Offline elcrniTopic starter

  • Regular Contributor
  • *
  • Posts: 98
  • Country: at
Re: Schmitt Buffer/Trigger with Encoder and buttons - Inverting...
« Reply #3 on: March 16, 2021, 01:01:11 pm »
also, if i am using inverting Schmitt IC, i could simply tell in the code that HIGH is LOW and vice versa?

I have found this one though:
https://www.mouser.at/ProductDetail/771-HC7014D112

Many thanks,
Alek
 

Offline MarkF

  • Super Contributor
  • ***
  • Posts: 2762
  • Country: us
Re: Schmitt Buffer/Trigger with Encoder and buttons - Inverting...
« Reply #4 on: March 16, 2021, 01:30:05 pm »
It's really not going to matter if the encoder lines are inverted or not.
Just so you do the same to BOTH lines.

You could invert them back in either software or hardware if you like.

The bigger issue I see it that you're not using a RC filter.
Just the capacitor.
The problem is that the encoder switches will present a short across the capacitors when they close.
Creating a non-current limited discharge.  Thus, reducing the life of the encoder contacts.
Use the full RC filtering as shown in some datasheets (i.e. PEC11 encoder datasheet for example).


Edit:
  Also 1uF capacitors are pretty large (slowing down the rotation response.
  I've found 10nF to 47nF range the best choice with the 10K resistors.
« Last Edit: March 16, 2021, 01:34:17 pm by MarkF »
 

Offline elcrniTopic starter

  • Regular Contributor
  • *
  • Posts: 98
  • Country: at
Re: Schmitt Buffer/Trigger with Encoder and buttons - Inverting...
« Reply #5 on: March 16, 2021, 01:39:41 pm »
Thanks MarkF!

Yes, that's the way i have it, sorry my scheme doesn't show that resistor on the signal line, just the pull-up one.
But yes, i am using RC filter the way you have it in your scheme, but, i have 220 ohm resistor on the signal line instead of 10k.

Many thanks,
Alek
 

Offline elcrniTopic starter

  • Regular Contributor
  • *
  • Posts: 98
  • Country: at
Re: Schmitt Buffer/Trigger with Encoder and buttons - Inverting...
« Reply #6 on: March 16, 2021, 01:41:33 pm »
It's really not going to matter if the encoder lines are inverted or not.
Just so you do the same to BOTH lines.

You could invert them back in either software or hardware if you like.

I am not worries about the encoder inverting the signal, but the few switches i would like to connect to Shcmitt as well. but i guess inverting those signals back should not be an issues either. Or i can just go with non-inverting IC.

Many thanks,
Alek
 

Offline MikeK

  • Super Contributor
  • ***
  • Posts: 1316
  • Country: us
Re: Schmitt Buffer/Trigger with Encoder and buttons - Inverting...
« Reply #7 on: March 16, 2021, 01:54:09 pm »
The Schmitt Trigger isn't going to do the debouncing for you.  You should probably learn how to do it in software.  Take a look at the ganssle article on switch debouncing.
 

Offline elcrniTopic starter

  • Regular Contributor
  • *
  • Posts: 98
  • Country: at
Re: Schmitt Buffer/Trigger with Encoder and buttons - Inverting...
« Reply #8 on: March 16, 2021, 01:56:48 pm »
The Schmitt Trigger isn't going to do the debouncing for you.  You should probably learn how to do it in software.  Take a look at the ganssle article on switch debouncing.

I like to do it in hardware, and i think RC filter did a great job in de-bouncing, Schmitt would be there just to iron out already debounced signal. Or am i completely off on this one?

thanks,
Alek
 

Offline Zero999

  • Super Contributor
  • ***
  • Posts: 20357
  • Country: gb
  • 0999
Re: Schmitt Buffer/Trigger with Encoder and buttons - Inverting...
« Reply #9 on: March 16, 2021, 02:04:05 pm »
The 74HC7014 has six chanels, which can be be used for switches, as well as the encoder. There's also the 74HC7541, which has eight channels.
https://uk.rs-online.com/web/p/buffers/4836689/

I should have said, I can't see the schematic, as I'm at work at the moment and the firewall blocks the image hosting site. You might be able to invert the switching signals by changing the pull-ups for pull-downs, or vice-versa.

I don't know whether the Ardunio Mega has Schmitt trigger inputs or not. Look at the data sheet of the microcontroller it uses.

 

Offline julian1

  • Frequent Contributor
  • **
  • Posts: 773
  • Country: au
Re: Schmitt Buffer/Trigger with Encoder and buttons - Inverting...
« Reply #10 on: March 16, 2021, 10:22:12 pm »
The rotary encoder has a 90degree relationship between edges, which provides lots of setup and hold time, when sampling levels. Unlike a (tactile) switch,  I *don't think* hardware debouncing actually gains you anything - regardless of whether decoding is done software or hardware. 
 

Offline Buriedcode

  • Super Contributor
  • ***
  • Posts: 1718
  • Country: gb
Re: Schmitt Buffer/Trigger with Encoder and buttons - Inverting...
« Reply #11 on: March 16, 2021, 10:58:29 pm »
If you don't want inverted outputs - just use two inverters in series?

Also, with regards to reading rotary encoders, I've found sampling is far more reliable than running on interrupts.  Sure, you can use interrupts at the start to interrupt your code to tell it someone is using the encoder, but a timer, periodically checking the status at a reasonable rate (200-500Hz?) once its detected provides more reliable results. Micros run so fast that routines that just constantly check the encoders output are effectively sampling at MHz and will pick up glitches.

Of course, an RC filter + schmitt trigger will help to cut these down, but you have to handle the encoder in software anyway, and you might have to play around with RC values if you want to get nice "clean" phasing between the two channels of the encoder.  It's extra hardware for something that can (and should) be done in software.  I generally just put on 10k/2.2n and connect straight to an IO.
 

Offline MarkF

  • Super Contributor
  • ***
  • Posts: 2762
  • Country: us
Re: Schmitt Buffer/Trigger with Encoder and buttons - Inverting...
« Reply #12 on: March 17, 2021, 12:08:01 am »
Thanks MarkF!

Yes, that's the way i have it, sorry my scheme doesn't show that resistor on the signal line, just the pull-up one.
But yes, i am using RC filter the way you have it in your scheme, but, i have 220 ohm resistor on the signal line instead of 10k.

Many thanks,
Alek

A 220 Ω resistor and a 47nF capacitor really are NOT doing much for you.

Remember the RC cutoff frequency is:  f = 1 / (2 * Ï€ * R * C)

   220Ω and 10nF = 15000 Hz    (very little impact on response)
   10KΩ and 10nF =  1600 Hz    (recommended values by Bourns PEC11 encoders)
   10KΩ and 47nF =   340 Hz    (okay if you don't turn the knob very fast)
 

Offline elcrniTopic starter

  • Regular Contributor
  • *
  • Posts: 98
  • Country: at
Re: Schmitt Buffer/Trigger with Encoder and buttons - Inverting...
« Reply #13 on: March 17, 2021, 09:41:41 am »
Many thanks for all your help guys! Lots of helpful tips.

As for the encoder, i have always and exclusively used it on interrupt pins, which was ok for most of the projects but now i have a radio signal encoder and analyzer, and once i activate encoder and start turning the knob, i get radio signal decoding errors, i would guess this is due to the fact that interrupt is stopping other processes to execute encoder input. So, i would gladly try the other way suggested by "Buriedcode"... but not sure how the code would look like, will search for examples.

thanks again guys!
Alek
 

Offline MarkF

  • Super Contributor
  • ***
  • Posts: 2762
  • Country: us
Re: Schmitt Buffer/Trigger with Encoder and buttons - Inverting...
« Reply #14 on: March 17, 2021, 11:10:49 am »
I assume you're saying 'interrupt on change'?
In which case, you will get many many interrupts if the encoder is noisy.

I use a fixed 500Hz interrupt to sample the encoder lines and only decode the encoder gray_code setting a global variable with a positive or negative number with the number of turns/detentes.  Increment the global count for clockwise turns and decrement the count for counter-clockwise turns.

After which, you use the global count outside the interrupt routine (i.e. the main loop) and clear it for the interrupt routine to restart the counting.  Inside the main loop, I copy the global count into a local variable and clear the global variable right away to avoid missing any counts.  Use the local variable count inside the main loop.  Note that you will NOT be processing each individual change but the number of counts since your last pass through the main loop.

The 500Hz sample rate works pretty well for me.  I would not sample much slower the 500Hz.  A 'fixed' sample rate avoids bursts of interrupts from noisy encoder lines.  You could almost consider it a form of debounce because the encoder lines can settle some between samples.
 

Offline elcrniTopic starter

  • Regular Contributor
  • *
  • Posts: 98
  • Country: at
Re: Schmitt Buffer/Trigger with Encoder and buttons - Inverting...
« Reply #15 on: March 17, 2021, 01:28:28 pm »
Thanks MarkF!

I have tried different approach now and moved off Interrupt pins.
My encoder code now runs inside the main loop (i guess at 16MHz) on atmega2560 controller.
I need to slow this way down as there is no need for it to run this fast.
Again, i am seeing errors in radio signal decoding probably due to the fact that encoder now is running inside main loop.

how do i slow down encoder checking rate/speed to something more reasonable, like 500Hz? (assuming someone has experience with arduino code)

Code: [Select]
void encoder_brightness(){

    state=(state<<1) | digitalRead(CLK_PIN) | 0xe000;

    if (state==0xf000){
       state=0x0000;
       if(digitalRead(DATA_PIN))
         counter++;
       else
         counter--;

       if (counter>15) {(counter = 15);}
       if (counter<0) {(counter = 0);}
}


and encoder_brightness() runs inside main loop.

I know we are now outside my main topic but i now when we are at it, i would really like to sort this one out.

Many thanks,
Alek




 

Offline MarkF

  • Super Contributor
  • ***
  • Posts: 2762
  • Country: us
Re: Schmitt Buffer/Trigger with Encoder and buttons - Inverting...
« Reply #16 on: March 17, 2021, 04:53:47 pm »
See if this helps:

   

And a little pseudo code as an outline:

Code: [Select]
// global variables
int count=0;  // encoder increment/decrement count

//************************************************************
void setup()
{
   // Set encoder pins as input
   . . .

   // Setup Timer 1 for 500Hz
   . . .

   // Enable interrupts
   sei();
}

//************************************************************
void loop()
{
   int local_count;

   if (count != 0) {
      // Get encoder turn count and reset it for future turns
      local_count = count;  // get encoder turns
      count = 0;            // reset global turn count

      // Use local_count to control your object, brightness or whatever
      . . .
      encoder_brightness(local_count);  // example: increase or decrease brightness by local_count amount
   }

   // Do other non-encoder related processing
   . . .
}

//************************************************************
ISR(TIMER1_CMPA_vect)
{
   // Read encoder lines
   . . .

   // Decode incrementing or decrementing count
   if (clockwise turn)
      count++;
   else if (counter_clockwise turn)
      count--;
}

« Last Edit: March 17, 2021, 06:06:07 pm by MarkF »
 

Offline elcrniTopic starter

  • Regular Contributor
  • *
  • Posts: 98
  • Country: at
Re: Schmitt Buffer/Trigger with Encoder and buttons - Inverting...
« Reply #17 on: March 17, 2021, 05:50:15 pm »
thanks man, thats some nice material.
i am not too familiar with interrupt timers, so will have to dive in more.

on a side note, what would happen if i just use millis and set it up to 2 millis for encoder checkup?
still sort of 500Hz...?

thanks
alek
 

Offline MarkF

  • Super Contributor
  • ***
  • Posts: 2762
  • Country: us
Re: Schmitt Buffer/Trigger with Encoder and buttons - Inverting...
« Reply #18 on: March 17, 2021, 06:20:33 pm »
thanks man, thats some nice material.
i am not too familiar with interrupt timers, so will have to dive in more.

on a side note, what would happen if i just use millis and set it up to 2 millis for encoder checkup?
still sort of 500Hz...?

thanks
alek

That would allow you to approximate reading and decoding the encoder pins.
It will NOT however allow you to do other tasks.
Not worth the effort in my opinion.

I typically do non-critical processing in the loop() function (such as updating a display screen) while sampling user inputs in the interrupt service code (basically just setting global flags to be used in the loop() function)(minimal processing in the interrupt code).

I would concentrate on setting up the code and the interrupt service routine (ISR).  You can toggle a pin inside the ISR() routine to check your setup and timing.  Then, add the encoder capability afterwards when you are confident with the basic code layout and timing.  Remember:  the ISR() function MUST complete BEFORE the next interrupt occurs.


One key edit to my previous pseudo code:  Add check for (count != 0), so you only execute that code within the loop when a change has been detected.  (see edited code)
« Last Edit: March 18, 2021, 11:26:24 am by MarkF »
 

Offline elcrniTopic starter

  • Regular Contributor
  • *
  • Posts: 98
  • Country: at
Re: Schmitt Buffer/Trigger with Encoder and buttons - Inverting...
« Reply #19 on: March 18, 2021, 01:59:35 pm »
ok, i took this the other way around, haha. First did the encoder but now hang at timing, still not sure how to pull this off.
my current code now goes as follows:

Code: [Select]
#include <EEPROM.h>
#include <LedControl.h>
#include <ezButton.h>
#include <TimeLib.h>
#include <RTClib.h>
#include <OneWire.h>
#include <DS1307RTC.h>


#define MAXIMCCLD 12         // output - CS/LOAD
#define MAXIMCCCLK 11        // output - CLOCK
#define MAXIMCCDATA 10       // output - DATA   
#define DS1307_I2C_ADDRESS 0x68 // define the RTC I2C address

ezButton button(7);  // create ezButton object that attach to pin 7;
LedControl MaximCC=LedControl(MAXIMCCDATA, MAXIMCCCLK, MAXIMCCLD, 1); // Define pins for Maxim 72xx and how many 72xx we use

int LED = 5;
int LED2 = 9;

volatile signed int counter_hour_start = EEPROM.read(2);
volatile signed int counter_minute_start = EEPROM.read(3);
volatile signed int counter_hour_end = EEPROM.read(4);
volatile signed int counter_minute_end = EEPROM.read(5);


// usually the rotary encoders three pins have the ground pin in the middle
enum PinAssignments {
  encoderPinA = 2,   // right
  encoderPinB = 3,   // left
};

  // a counter for the dial
signed int lastReportedPos_hour_start = 1;   // change management
signed int lastReportedPos_minute_start = 1;   // change management
signed int lastReportedPos_hour_end = 1;   // change management
signed int lastReportedPos_minute_end = 1;   // change management


// interrupt service routine vars
boolean A_set = false;
boolean B_set = false;

int previousSecond = 0;
int tensofhours, singlehours, tensofminutes, singleminutes,tensofhours1, singlehours1, tensofminutes1, singleminutes1;

//==============================================================================
// SETUP
//==============================================================================

void setup() {

  pinMode(LED, OUTPUT);
  pinMode(LED2, OUTPUT);

  pinMode(encoderPinA, INPUT);
  pinMode(encoderPinB, INPUT);
 
  // encoder pin on interrupt 0 (pin 2)
  attachInterrupt(0, doEncoderA, CHANGE);
  // encoder pin on interrupt 1 (pin 3)
  attachInterrupt(1, doEncoderB, CHANGE);


 
  MaximCC.shutdown(0,false);
  MaximCC.setIntensity(0,15);
  MaximCC.clearDisplay(0);
  button.setDebounceTime(50); // set debounce time to 50 milliseconds
  button.setCountMode(COUNT_FALLING);
  setSyncProvider(RTC.get); // the function to get the time from the RTC

  tensofhours = counter_hour_start / 10;
  singlehours = counter_hour_start % 10;
  tensofminutes = counter_minute_start / 10;
  singleminutes = counter_minute_start % 10;
  tensofhours1 = counter_hour_end / 10;
  singlehours1 = counter_hour_end % 10;
  tensofminutes1 = counter_minute_end / 10;
  singleminutes1 = counter_minute_end % 10;
}


//==============================================================================
// LOOP
//==============================================================================

void loop() {

tasksEverySecond();

button.loop(); // MUST call the loop() function first
unsigned long count = button.getCount();
   
if (count>0) {
  encoder_alarm();
  }
}

//==============================================================================
// tasksEverySecond
//==============================================================================
void tasksEverySecond()
{
  if (second() != previousSecond)
  {
    previousSecond = second();

    displayRtcTime();
    ledTest();
  }
}


//==============================================================================
// ENCODER ALARM
//==============================================================================

void encoder_alarm(){

  unsigned long count = button.getCount();

    // reset button count when we cycle through all digit groups and set an alarm
    if (count > 6) {
    button.resetCount();
    digitalWrite(LED, LOW);
  }

  //--------------------- HOURS alarm STARTS at ------------------------//
 


    if (lastReportedPos_hour_start != counter_hour_start) {
      if (counter_hour_start>23) {(counter_hour_start = 0);}
      if (counter_hour_start<0) {(counter_hour_start = 23);}

      tensofhours = counter_hour_start / 10;
      singlehours = counter_hour_start % 10;

      lastReportedPos_hour_start = counter_hour_start;
  }
      EEPROM.update(2,counter_hour_start);


  //--------------------- MINUTES alarm STARTS at ------------------------//
 
 

    if (lastReportedPos_minute_start != counter_minute_start) {
      if (counter_minute_start>59) {(counter_minute_start = 0);}
       if (counter_minute_start<0) {(counter_minute_start = 59);}

       tensofminutes = counter_minute_start / 10;
       singleminutes = counter_minute_start % 10;

      lastReportedPos_minute_start = counter_minute_start;

       EEPROM.update(3,counter_minute_start);
  }
 
  //--------------------- HOURS alarm ENDS at ------------------------//
 

    if (lastReportedPos_hour_end != counter_hour_end) {
      if (counter_hour_end>23) {(counter_hour_end = 0);}
      if (counter_hour_end<0) {(counter_hour_end = 23);}

      tensofhours1 = counter_hour_end / 10;
      singlehours1 = counter_hour_end % 10;

      lastReportedPos_hour_end = counter_hour_end;
  }
      EEPROM.update(4,counter_hour_end);

 
  //--------------------- MINUTES alarm ENDS at ------------------------//
 


    if (lastReportedPos_minute_end != counter_minute_end) {
      if (counter_minute_end>59) {(counter_minute_end = 0);}
       if (counter_minute_end<0) {(counter_minute_end = 59);}

       tensofminutes1 = counter_minute_end / 10;
       singleminutes1 = counter_minute_end % 10;

      lastReportedPos_minute_end = counter_minute_end;

       EEPROM.update(5,counter_minute_end);
  }

 
  //--------------------- 7 Segment display  ------------------------//

  if (count == 1 || count == 6) {
    MaximCC.setChar(0,7,tensofhours,false);
    MaximCC.setChar(0,6,singlehours,true);
    MaximCC.setChar(0,5,tensofminutes,false);
    MaximCC.setChar(0,4,singleminutes,true);
    MaximCC.setChar(0,3,tensofhours1,false);
    MaximCC.setChar(0,2,singlehours1,true);
    MaximCC.setChar(0,1,tensofminutes1,false);
    MaximCC.setChar(0,0,singleminutes1,true); 
    digitalWrite(LED, HIGH);
  }
 
  if (count == 2) {
    MaximCC.setChar(0,7,tensofhours,false);
    MaximCC.setChar(0,6,singlehours,true);
  } else if (count != 1 && count != 6){
    MaximCC.setChar(0,6,singlehours,false);
  }

  if (count == 3) {
    MaximCC.setChar(0,5,tensofminutes,false);
    MaximCC.setChar(0,4,singleminutes,true);
  } else if (count != 1 && count != 6) {
    MaximCC.setChar(0,4,singleminutes,false);
  }

  if (count == 4) {
    MaximCC.setChar(0,3,tensofhours1,false);
    MaximCC.setChar(0,2,singlehours1,true);
  } else if (count != 1 && count != 6) {
    MaximCC.setChar(0,2,singlehours1,false);
  }

  if (count == 5) {
    MaximCC.setChar(0,1,tensofminutes1,false);
    MaximCC.setChar(0,0,singleminutes1,true);
  } else if (count != 1 && count != 6) {
    MaximCC.setChar(0,0,singleminutes1,false);
  }
}

//==============================================================================
// displayRtcTime
//==============================================================================

void displayRtcTime()
{
  unsigned long count = button.getCount();
 
  if (count == 0){
  MaximCC.setChar(0, 7, (hour() / 10), false);
  MaximCC.setChar(0, 6, (hour() % 10), false);
 
  MaximCC.setChar(0, 5, '-', false);
  MaximCC.setChar(0, 4, (minute() / 10), false);
  MaximCC.setChar(0, 3, (minute() % 10), false);

  MaximCC.setChar(0, 2, '-', false);
  MaximCC.setChar(0, 1, (second() / 10), false);
  MaximCC.setChar(0, 0, (second() % 10), false);
 }
}

//==============================================================================
// ledTest
//==============================================================================
void ledTest(){
  int midnight;
  int powersaving;
  int startTime = counter_hour_start * 100 + counter_minute_start;
  int endTime = counter_hour_end * 100 + counter_minute_end;
  int timeNow = hour() * 100 + minute();
 

  if (endTime == 0000 && startTime != 0000){
    endTime = 2359;
  }
 
   
   if (timeNow >= startTime && timeNow < endTime)  {
    powersaving = true;
   } else {
    powersaving = false;
   }
 
  if (powersaving == true){
    digitalWrite(LED2, HIGH);
  } else {
    digitalWrite(LED2, LOW);
  }
}



// Interrupt on A changing state
void doEncoderA() {
 
  unsigned long count = button.getCount();
  // Test transition, did things really change?
  if ( digitalRead(encoderPinA) != A_set ) { // debounce once more
    A_set = !A_set;

    // adjust counter + if A leads B
    if (( A_set && !B_set ) && (count == 2))
      counter_hour_start += 1;
    if (( A_set && !B_set ) && (count == 3))
      counter_minute_start += 1;
    if (( A_set && !B_set ) && (count == 4))
      counter_hour_end += 1;
    if (( A_set && !B_set ) && (count == 5))
      counter_minute_end += 1;

  }
}
// Interrupt on B changing state, same as A above
void doEncoderB() {
 
  unsigned long count = button.getCount();
  if ( digitalRead(encoderPinB) != B_set ) {
    B_set = !B_set;
    //  adjust counter - 1 if B leads A
    if (( B_set && !A_set ) && (count == 2))
      counter_hour_start -= 1;
    if (( B_set && !A_set ) && (count == 3))
      counter_minute_start -= 1;
    if (( B_set && !A_set ) && (count == 4))
      counter_hour_end -= 1;
    if (( B_set && !A_set ) && (count == 5))
      counter_minute_end -= 1;
  }
}


Many thanks,
Alek
 

Offline MarkF

  • Super Contributor
  • ***
  • Posts: 2762
  • Country: us
Re: Schmitt Buffer/Trigger with Encoder and buttons - Inverting...
« Reply #20 on: March 18, 2021, 08:19:56 pm »
ok, i took this the other way around, haha. First did the encoder but now hang at timing, still not sure how to pull this off.
my current code now goes as follows:

Code: [Select]
void setup() {

  pinMode(encoderPinA, INPUT);
  pinMode(encoderPinB, INPUT);
 
  // encoder pin on interrupt 0 (pin 2)
  attachInterrupt(0, doEncoderA, CHANGE);      // NO.  NO. NO.  DELETE.
  // encoder pin on interrupt 1 (pin 3)
  attachInterrupt(1, doEncoderB, CHANGE);      // NO.  NO. NO.  DELETE.

}

Many thanks,
Alek

Sorry.
Now you get to re-write it.

To start, you DO NOT do interrupt-on-change.
Remove all code related to interrupt-on-change.

Your interrupt ISR() (which is missing) is called at a fixed rate (I suggest 500Hz).
Inside the ISR(), it would be best the have both encoder lines on the same Mega port and to read the Port to get both bits simultaneously. 
Single read of the port instead of two pin reads.  (i.e. read the port --> then mask the two bits --> decode gray code --> increment/decrement turn count.)
 
To get started, view the video and setup the ISR() routine.  The interrupt and setup in the video (near the end of thee video) is for an UNO and needs to be slightly modified for the Mega. 
Download the Mega datasheet and refer to section 17.
Then, test the code to insure the ISR() is called at 500Hz (or the rate you decide upon).
 

Offline nctnico

  • Super Contributor
  • ***
  • Posts: 28429
  • Country: nl
    • NCT Developments
Re: Schmitt Buffer/Trigger with Encoder and buttons - Inverting...
« Reply #21 on: March 18, 2021, 08:25:24 pm »
Many thanks for all your help guys! Lots of helpful tips.

As for the encoder, i have always and exclusively used it on interrupt pins, which was ok for most of the projects but now i have a radio signal encoder and analyzer, and once i activate encoder and start turning the knob, i get radio signal decoding errors, i would guess this is due to the fact that interrupt is stopping other processes to execute encoder input. So, i would gladly try the other way suggested by "Buriedcode"... but not sure how the code would look like, will search for examples.
Yeah, you just learned never to use interrupts on GPIO pins the hard way. Never ever use interrupts on GPIO pins because you can't predict when the interrupts will happen and thus the timing of your software is no longer predictable. There have been lengthy threads on this forum about handling a rotary encoder in software.

https://www.eevblog.com/forum/microcontrollers/using-a-rotary-encoder/
« Last Edit: March 18, 2021, 08:28:38 pm by nctnico »
There are small lies, big lies and then there is what is on the screen of your oscilloscope.
 

Offline MarkF

  • Super Contributor
  • ***
  • Posts: 2762
  • Country: us
Re: Schmitt Buffer/Trigger with Encoder and buttons - Inverting...
« Reply #22 on: March 18, 2021, 09:28:33 pm »
Also, remove void doEncoderA() and void doEncoderB() functions.

They will be replaced by an ISR(TIMER1_CMPA_vect) function.
This ISR() function will both read the encoder pins and the encoder switch (if it has one) and then setting a global turn count variable and a global switch depressed/released flag.

But as I said a few times now, you need to implement a timer interrupt by configuring the timer and enabling its interrupt in the setup() function and writing the ISR() function to read the encoder pins.
 

Offline elcrniTopic starter

  • Regular Contributor
  • *
  • Posts: 98
  • Country: at
Re: Schmitt Buffer/Trigger with Encoder and buttons - Inverting...
« Reply #23 on: March 18, 2021, 09:50:24 pm »
DOH!

Oh well, back tp the drawing board, i have a feeling this will be a long weekend.
Trying to find a close example of a code to go buy, a bit out of my skill level to start from scratch, but maybe a time to learn something new.


Thanks guys!
Alek
 

Offline MarkF

  • Super Contributor
  • ***
  • Posts: 2762
  • Country: us
Re: Schmitt Buffer/Trigger with Encoder and buttons - Inverting...
« Reply #24 on: March 18, 2021, 10:10:14 pm »
DOH!

Oh well, back tp the drawing board, i have a feeling this will be a long weekend.
Trying to find a close example of a code to go buy, a bit out of my skill level to start from scratch, but maybe a time to learn something new.


Thanks guys!
Alek

I gave you some pseudo code.  It's 80% of the code.
Just fill in the functions from the example video with small changes related to the Mega. 
(i.e. the register names for Timer1 are slightly different and the register bits may be different)
Plus, you will need to calculate new times to get 500Hz.

You're making a mountain out of a mole hill.
« Last Edit: March 18, 2021, 10:14:07 pm by MarkF »
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf