Can anyone figure out why KEY_LEFT_SHIFT is not being sent out?

I have been working with Chat GPT trying to get it to write some code for an Encoder to cycle through a set of seven sections, sending out a series of Tabs each time it detents to the right, and a series of Shift+Tabs every time it detents to the left. Here is the code it has written:

#include <Keyboard.h>

const int encoderPin1 = 2;  // Rotary encoder pin 1
const int encoderPin2 = 3;  // Rotary encoder pin 2
const int buttonPin = 4;    // Rotary encoder button pin

int lastState;
int currentState;
int section = 0;

const int numSections = 7;
const char* sectionNames[] = {"Text Entry", "Types", "Instruments", "Styles", "Banks", "User", "Blank Section"};

void setup() {
  Keyboard.begin();
  pinMode(encoderPin1, INPUT_PULLUP);
  pinMode(encoderPin2, INPUT_PULLUP);
  pinMode(buttonPin, INPUT_PULLUP);
  lastState = digitalRead(encoderPin1);
}

void loop() {
  // Read the current state of the rotary encoder
  int state = digitalRead(encoderPin1);
  if (state != lastState) {
    if (digitalRead(encoderPin2) != state) {
      section++;
      if (section >= numSections) {
        section = 0;
      }
      if (section == 6) {
        // Send 5 tabs for Blank Section
        for (int i = 0; i < 5; i++) {
          Keyboard.write(KEY_TAB);
        }
      } else {
        Keyboard.write(KEY_TAB);
      }
      Serial.print("Section: ");
      Serial.println(sectionNames[section]);
      delay(100); // debounce delay
    } else {
      section--;
      if (section < 0) {
        section = numSections - 1;
      }
      if (section == 6) {
        // Send 5 shift+tabs for Blank Section
        Keyboard.write(KEY_LEFT_SHIFT);
        for (int i = 0; i < 5; i++) {
          Keyboard.write(KEY_TAB);
        }
        Keyboard.release(KEY_LEFT_SHIFT);
      } else {
        Keyboard.write(KEY_LEFT_SHIFT);
        Keyboard.write(KEY_TAB);
        Keyboard.release(KEY_LEFT_SHIFT);
        Keyboard.release(KEY_TAB);        
      }
      Serial.print("Section: ");
      Serial.println(sectionNames[section]);
      delay(100); // debounce delay
    }
  }
  lastState = state;
  
  // Check if the encoder button has been pressed
  if (digitalRead(buttonPin) == LOW) {
    Keyboard.write(KEY_RETURN);
    Serial.println("Enter");
    delay(500); // debounce delay
    Keyboard.release(KEY_RETURN);
  }
}

The code is working ok for the right turns, meaning: it is sending out Tabs as it should. But for whatever reason, it will not send out the Shift+Tabs when the encoder turns to the left. It just continues cycling through the sections, moving from left to right, even though it should at that point cycle by moving from right to left.

In looking at the code, it's clear to me that the lines germane to this operation are lines 54-59. They look like they should work-all kind of standard fare. But no matter what, the code is not working as it should when the encoder is turned to the left.

Can anybody out there figure out what's wrong with the code, and a possible solution?

Thanks for the help.
Clay

As Chat GPT wrote the code why don't you ask it what the problem is ?

1 Like

Maybe you could also ask it what the variable "currentState" is for, and why it's a global.

Good question: I have many, many times over the course of the last 24 hours. Chat GPT, while being truly amazing, still does have limitations. I have been able to ask it to rewrite code successfully, and I have also been given code that is not functional at all.

One of the biggest pitfalls of working with Chat GPT is in how it's memory works: I (and it, together) have gone through SO many iterations of this obviously pretty complicated request-most of which have fallen short-that when I did receive some code that worked somewhat well, I at that point want to just stay with that code in the overall, and just have Chat GPT massage it here and there. This seems simple enough, right?

Yeah, but it doesn't work that way with Chat GPT. It will often take your request to slightly revise the code you like as a request to write completely new code, as if it's starting to throw spaghetti against a wall, trying to please you. And then commenting to Chat GPT to go back to rewriting the code that it gave you a while back-the code that was working rather well-doesn't work either.

It's as if it has completely forgotten the code, and I have yet to find a way to adequately re-direct Chat GPT, in a way that will force it to stay focused on some code you really like. At least not if, as I've said before, the ask is a rather complicated one, and as well, if you have had to correct it multiple times.

It's as if it starts to get insecure that it's not pleasing you, and then gets so desperate to make you happy that it thinks the wisest choice is to change course completely. Explaining to Chat GPT that this is not what you want, and that you want it to go back to what you were working on before is to no avail.

So, Chat GPT is great-but at this point, there's no substitute for Human Help. That's why.

The short answer is: I have asked it to fix it. It couldn't.

My guess is that with all the if-else conditions the code may not be entering the section you need. Try some Serial prints to see where you actually are. Or perhaps recraft as a state machine.

Here's a novel idea .... write your own code.

1 Like

That's maybe a good intuition on your part, SemperIdem. I don't see currentState referred to again, anywhere in the code, after being declared as a variable.

That's another thing about Chat GPT: it's definitely not infallible. It makes mistakes in plain sight-mistakes you'd think that a "computer" would catch. And it has also written incomplete code, suggested solutions to code involving inserting new calls, that are referring to things that haven't yet been declared, and yet it'll speak about these things as if these undeclared items are obviously in the code.

So it can be perplexing dealing with Chat GPT.

Did Chat GPT insert the Serial.println() in the sketch and forgot to initialize Serial in setup()?

And it debounces with delay(100) and delay(500) ... :wink:

1 Like

gfvalvo-thanks for the feedback.

I am EXTREEEEMLY new to coding. What I've done with Arduino/coding amounts to less than 2 weeks experience. I am learning fast, and I am enjoying it along the way, but still, what I know amounts to things like understanding some functions, being able to vaguely recognize some routines: things like that.

I am NO WHERE NEAR the point of being even a novice with writing-much less understanding-syntax. And yet I have a strong conceptual understanding of what I want. And so, in discovering Chat GPT, it has seemed like at least a partial solution for someone like me.

Well, yup. Chat GPT did forget to do that, because I didn't do that. And as my last post should make clear: given how new I am to coding, I certainly could've made the same mistake. But that was Chat GPT.

As far as the different debouncing values, I changed the delay on line 54 from 100 to 500 because 100 was ineffective with stopping debounce on the encoder button.

Should I change all the delays to 500? Is this considered better form?

If it were, would we call it "Pope"?

Hi cattledog-thanks for the reply.

You're suggesting I try some Serial prints. This is not the same thing as, say, the Serial printing happening in the Serial Monitor? I'm trying to see if that's what you're asking me to do.

If you're asking me to monitor the actions that are taking place while turning the Encoder then, unless there's something more to this that I don't yet understand, I'm already doing this:
I get a serial print in the monitor-telling me what section has just been entered (i.e.: "Types", "Instruments", etc.) Is this what you're meaning?

Or are you talking about another function that I don't yet know about? Like a play-by-play printing of the code that is being accessed as it runs through it's loop?

Not sure how that'd be possible (because it'd be reporting SO fast), but I thought I should get clarification from you.

And question #2: what do you mean by recrafting as a "state machine"?

:sweat_smile: :sweat_smile: :sweat_smile:

Yes. You have very complex if/else logic leading to the output you want, but you only print the Section in a couple of places. The encoder may be switching through the sections correctly, but the action based on which section you are in may not be taking place correctly. You can use Serial printing output to tell you where you are in the code.

More questions that you could ask Chat GPT about

This forum works best when a user has done their best to write a sketch to meet their requirements and needs help with errors or functionality that is not working

You have done none of this, but what you have done is it to reinforce the view held by many experienced forum members that the posting of flawed code written by AI should be banned from the forum.

Basically, what you are saying is that you have some code that you do not understand provided by an AI system that does not understand your requirements and could someone fix it for you

I am sorry, but on that basis I doubt that the problems with the code will be resolved in this topic.

In my view, instead of spending time trying to get Chat GPT to write what you want your time would be better used learning to code in C++

1 Like

No, using delays() for debouncing is usually considered "bad habit" because it slows down reactivity of the sketch ...

There are of course applications where you only want to use the first "edge" of switching but usually one wants the machine to quickly react to human input. Feel free to google for "debouncing buttons" . There is plenty of material available ...

I have quickly converted your sketch to Wokwi with some small changes:

//#include <Keyboard.h>

const int encoderPin1 = 2;  // Rotary encoder pin 1
const int encoderPin2 = 3;  // Rotary encoder pin 2
const int buttonPin = 4;    // Rotary encoder button pin

int lastState;
int currentState;
int section = 0;

const int numSections = 7;
const char* sectionNames[] = {"Text Entry", "Types", "Instruments", "Styles", "Banks", "User", "Blank Section"};

#define KEY_TAB "KEY_TAB"
#define KEY_LEFT_SHIFT "KEY_LEFT_SHIFT"
#define KEY_RETURN "KEY_RETURN"


struct kbt {
  void begin();
  void write(String aKey);
  void release(String aKey);
} Keyboard;

void kbt::begin() {}
void kbt::write(String aKey) {
  Serial.print(aKey + " ");
}
void kbt::release(String aKey) {
  Serial.print(aKey + "_released ");
}

void setup() {
  Serial.begin(115200);
  Keyboard.begin();
  pinMode(encoderPin1, INPUT_PULLUP);
  pinMode(encoderPin2, INPUT_PULLUP);
  pinMode(buttonPin, INPUT_PULLUP);
  lastState = digitalRead(encoderPin1);
}

void loop() {
  // Read the current state of the rotary encoder
  int state = digitalRead(encoderPin1);
  if (state != lastState) {
    if (digitalRead(encoderPin2) != state) {
      section++;
      Serial.println("section++\t"+String(section));
      if (section >= numSections) {
        section = 0;
      }
      if (section == 6) {
        // Send 5 tabs for Blank Section
        for (int i = 0; i < 5; i++) {
          Keyboard.write(KEY_TAB);
        }
      } else {
        Keyboard.write(KEY_TAB);
      }
      Serial.print("Section: ");
      Serial.println(sectionNames[section]);
      delay(100); // debounce delay
    } else {
      section--;
      Serial.println("section--\t"+String(section));
      if (section < 0) {
        section = numSections - 1;
      }
      if (section == 6) {
        // Send 5 shift+tabs for Blank Section
        Keyboard.write(KEY_LEFT_SHIFT);
        for (int i = 0; i < 5; i++) {
          Keyboard.write(KEY_TAB);
        }
        Keyboard.release(KEY_LEFT_SHIFT);
      } else {
        Keyboard.write(KEY_LEFT_SHIFT);
        Keyboard.write(KEY_TAB);
        Keyboard.release(KEY_LEFT_SHIFT);
        Keyboard.release(KEY_TAB);
      }
      Serial.print("Section: ");
      Serial.println(sectionNames[section]);
      delay(100); // debounce delay
    }
  }
  lastState = state;

  // Check if the encoder button has been pressed
  if (digitalRead(buttonPin) == LOW) {
    Keyboard.write(KEY_RETURN);
    Serial.println("Enter");
    delay(500); // debounce delay
    Keyboard.release(KEY_RETURN);
  }
}

see https://wokwi.com/projects/361379619854799873

I just exchanged the Keyboard function by a simple struct that prints strings (see the #defines).

And I inserted Serial.begin() plus two lines where the variable section is increased and decreased.

What I found is this:

  • If you turn right (I adjusted the encoderPins according to what you said is working) "section" is decreased two times per click.
  • If you turn left "section" is increased by 1 and then decreased by 1 ... Thus staying at the same value after one click.

Good luck!
ec2021

I'm sorry you're feeling such consternation. I am not someone who is trying to get someone else to write my code. I'm someone who has an idea who's requirements far outstretch my present understandings.

It was not my intention to besmirch Chat GPT: again-I think it is ABSOLUTELY AMAZING. It has done things which have deeply impressed me. It nonetheless can be thrown. This is what I was trying to say.

This is the query I gave to Chat GPT (I didn't initially include it because I was trying not to overload readers with information. But, here it is:

"

Using an Arduino Leonardo and the Keyboard Library I'd like to use a rotary encoder to be able to scroll through 7 different sections. Incrementing or decrementing one detent at a time on the encoder should change sections, going forward one section to the next, or moving backward, one to the next, depending on whether the encoder is turning right or left. Each section has a name: the first section is Text Entry, the second section is Types, the third section is Instruments, the fourth section is Styles, the fifth section is Banks, the sixth section is User and the seventh section is Blank Section. The encoder should send out 1 Tab whenever it increments into the sections: Text Entry, or Types, or Instruments, or Styles, or Banks, or User, and send out 5 Tabs when it increments into Blank Section. The encoder should send out 1 Shift+Tab whenever it decrements into the sections: Text Entry, or Types, or Instruments, or Styles, or Banks, or User, and send out 5 Shift+Tabs when it decrements into Blank Section. These 7 sections need to wrap around in a circle, wherein the first section (which is Text Entry) is connected to the last section (which is Blank Section), so that they can be endlessly cycled through by the turning of the encoder if desired. Finally, there needs to be a Serial print function included so that I can see the name of the section I am in, at any time. I will need to add a function to the encoder button: I want it to send out an Enter. Please show when the Encoder button sends out Enter in the Serial Monitor"

So, again, for the third time: that Chat GPT has been fashioned in a way that actually enables it to parse through such a request, and give out what it has given is just jaw-droppingly impressive to me.


I don't know when was the last time that you, UKHeliBob were a beginner at something. Perhaps you have forgotten what it felt like. I'm simply trying to learn. I have coded some things with success-some things that have been FAR simpler than this code. I am not scarred to ask for help when I need it.

Hopefully there are more people out there who realize that you have to start somewhere, and so are willing to try to help me learn along the way.

I am fine if you should decide that you don't want to help me at all-especially seeing as you have given no help as of yet, but instead have offered one inquiry asking me why I don't just go back to Chat GPT, followed up with a passionate admonishment. All because I'm new.

Feel free to not help me anymore.

I have not tried out your code yet, ec2021, but just out of hand I want to thank you for trying to help me! I really appreciate it.

I'm going to wolf down some lunch, and then I'll Upload your code, and go from there. I'll update the thread.

I am still a beginner at lots of things, so I know how you feel

The problem, at least in my opinion, is that you are going about learning how to code in C++ in the wrong way. ChatGPT is amazing in what it can do but it is not a teacher

1 Like

I am not trying to get Chat GPT to teach me much of anything. I am going to it to help me bring a concept-one that far outpaces my current abilites-into fruition, and that's it. Will I pick up a few more tricks, here and there by studying the code given to me? Perhaps. But I'm not looking to Chat GPT to teach.

I have learned an ENORMOUS amount of skills from YouTube: Electronics-both Theory and Engineering, Welding (though I am already a trained welder), Woodworking; the list goes on and on. This is where I will do the lion's share of my education on working within the Arduino IDE, and, probably, a good deal of programing in C++.

Don't know how you've done it, but however you did do it, that was great for you. This is how I do it. It works for me.