author2
2Instructables269,608Views136CommentsUK

Tell us about yourself!

Achievements

100+ Comments Earned a bronze medal
10K+ Views Earned a bronze medal
  • Improved Arduino Rotary Encoder Reading

    I'm sure you could translate it to a high level language but I doubt it would be understood any better by your compiler if you are still using the same core. Why don't you go to the core that applies to your sketch and find out how they do port reads in that core? I'd guess (without checking - you could do that) GPIOA->IDR is just a macro/shorthand for reading the registers that contain the status of a bank of pins.

    View Instructable »
  • Improved Arduino Rotary Encoder Reading

    Try searching the error you had. The first result Google threw up for me when I did was that someone was using the wrong/different stm32 core in the arduino ide.

    View Instructable »
  • Improved Arduino Rotary Encoder Reading

    It's not the interrupts so much (but you will hit issues with that too), more that the instruction to read the whole port is different on the 4809. You could start with https://forum.arduino.cc/index.php?topic=630845.0 to see how the port read could work on the 4809 or replace with digitalRead()s. If you find a successful port to the 4809, please post the code here for others to learn from.

    View Instructable »
  • Improved Arduino Rotary Encoder Reading

    Hi, glad it helped! It certainly won't work as-is on a Wemos D1 Mini as significant elements of the code are written for the ATMEGA328P chip in the Arduino Nano/Uno/Pro Mini etc. However, the ESP8266 in the D1 Mini does allow interrupts to be set in the Arduino IDE: https://randomnerdtutorials.com/interrupts-timers-esp8266-arduino-ide-nodemcu/There are some clues about directly reading pin ports on the ESP8266 here: https://forum.arduino.cc/index.php?topic=423340.0 but it sounds like you'd be able to read fast enough using a pair of digitalRead()s in each ISR (in Arduino IDE) because the ESP8266 is much faster clocking and it looks like the driver code for them to make them work in Arduino has less delay (overhead) than for the ATMEGA328. So it could be quite simple to adapt. Good luck!

    View Instructable »
  • Improved Arduino Rotary Encoder Reading

    Thanks @Trackieman, I've not tested but I'm sure it will be helpful for people.

    View Instructable »
  • Easy Arduino Menus for Rotary Encoders

    You're welcome!

    Glad you got it working. I'm not going to update the code but at least your comments will help if people who are confused by this continue reading further than "copy-paste" on the code section. Please don't take offence but this is not code I intend to maintain. Not least because Instructibles requires you to have a pro account to publish in "code" format and I only had a complimentary pro account when I posted these 'ibles. If I try and change them now the formatting would likely be lost and that would make understanding it far harder than a deprecated but functioning method for setting interrupts.

    View Instructable »
  • Easy Arduino Menus for Rotary Encoders

    Hey @bowlerhatman, of course there will be some necessary code changes for a chip that's not the ATMEGA328P - hopefully that was clear from the discussion about portability in my other instructible. Would you care to post images of your encoder and wiring?My inclination would be to try connecting a multimeter in continuity mode (or oscilliscope if you have one) to ensure the voltage logic between detents is as expected with your current wiring.

    Perhaps "mention" would have been better than "discussion". But the point was that with that code you should expect to have to change the port manipulation elements to port it to other chips.Did you check against this tip in that instructible:"Make sure you find out where the detent state is for your encoder and adapt your code accordingly. My example uses an encoder whose pins are both disconnected from ground and are pulled high by their respective input pullup resistors. This drives my selection of a RISING interrupt. If both pins were connected to ground when at detent, they would need code which was looking for FALLING pin voltage."?Chips come with pins assigned in banks, called ports. Arduino assigns its own pin numbers to particular pins, so that they …

    see more »

    Perhaps "mention" would have been better than "discussion". But the point was that with that code you should expect to have to change the port manipulation elements to port it to other chips.Did you check against this tip in that instructible:"Make sure you find out where the detent state is for your encoder and adapt your code accordingly. My example uses an encoder whose pins are both disconnected from ground and are pulled high by their respective input pullup resistors. This drives my selection of a RISING interrupt. If both pins were connected to ground when at detent, they would need code which was looking for FALLING pin voltage."?Chips come with pins assigned in banks, called ports. Arduino assigns its own pin numbers to particular pins, so that they can match the peripheral functions across chips and achieve some commonality that e.g. PWM will be available on D5 for as many Arduinos as possible (to enable analogWrite() to be portable between Arduinos). Finally, there are hardware interrupts. The ATMEGA328P has two, starting at 0 and ending with 1. The ATMEGA32U4 appears to have 4 hardware interrupts (0-4). It just so happens that port pin number, arduino pin number and hardware interrupt number have very little to do with each other. Does that help?If you are sure there are no other components involved in your wiring, the schematic looks good, as long as it is correct! What value capacitors have you used? Do you have a spec for your encoder - model number or photo?Without going in to the pin assignments, port masking and interrupt setting, I think you would do well to firstly check that your encoder is contacting each pin to ground just using some form of continuity checker. If you don't have a multimeter, you could use a battery, suitable value resistor and LED to check this.Once you have confirmed that you are definitely seeing both pin A and pin B make AND break contact with pin C for each detent, make note of whether the connection is open or closed at detent.Then I think you should set up a simple sketch with only one of the A or B pins connected and set up the hardware interrupt. Then just make sure you can get e.g. Serial monitor or LED flash from a separate GPIO when the interrupt fires. Once you have this, move on to add the other pin B or A and its respective interrupt. Confirm now that both interrupts are firing.From a quick look at the pinout of the Leonardo, you need to do something like this in setup (I'll leave it to you to set some suitable volatile variables to use as flags in your ISR):pinMode(2, INPUT_PULLUP);pinMode(3, INPUT_PULLUP);attachInterrupt(0,yourRoutineA,CHANGE);attachInterrupt(1,yourRoutineB,CHANGE);Then write your ISRs called yourRoutine() to change the value of a flag variable.Get your main loop to check for changes to the flag variable, reset it and notify you somehow (LED/serial monitor). See how you get on.

    View Instructable »
  • Easy Arduino Menus for Rotary Encoders

    @Boomer48, you could do that, yes. Someone in the comments here or, more likely, in my other instructible on reading rotary encoders has left a comment with a way to use only one external interrupt with the encoder, leaving the other external interrupt free for other uses.

    View Instructable »
  • Easy Arduino Menus for Rotary Encoders

    @Spa2036 you can add "Pin Change Interrupts" (PCI) to other pins on the ATMEGA328 based Arduinos. They are not quite as configurable as the hardware interrupts because they will fire every time the logic state changes (rather selecting only RISING or FALLING) but you can do a quick digitalRead in the interrupt service routine to confirm the pin's new state. The conclusion is that using a PCI will save you from having to change any of your existing wiring or interrupt-handling code.

    View Instructable »
  • Improved Arduino Rotary Encoder Reading

    I believe the KY-040 will work as expected with this sketch. I do note that if it is one based on a PCB breakout, there can be capacitors and pullup resistors on there too. And the silkscreen labelling of the pins can be misleading in my opinion, so do take the time to figure out the pinout (which you could research while you wait for the mail to arrive). For the 12 item limit, you could just place a function that you run every time you increment or decrement your encoderPos within each menu setting. For example:// Function to keep the encoderPos value in boundssubMenuLimitA(uint8_t upperLimit){ // check if we have exceeded the limit if (encoderPos > upperLimit) { // if so, roll/wrap the encoder count round to the beginning encoderPos = 0; }}This is very basic. It will roll the …

    see more »

    I believe the KY-040 will work as expected with this sketch. I do note that if it is one based on a PCB breakout, there can be capacitors and pullup resistors on there too. And the silkscreen labelling of the pins can be misleading in my opinion, so do take the time to figure out the pinout (which you could research while you wait for the mail to arrive). For the 12 item limit, you could just place a function that you run every time you increment or decrement your encoderPos within each menu setting. For example:// Function to keep the encoderPos value in boundssubMenuLimitA(uint8_t upperLimit){ // check if we have exceeded the limit if (encoderPos > upperLimit) { // if so, roll/wrap the encoder count round to the beginning encoderPos = 0; }}This is very basic. It will roll the encoderPos variable round to zero if you go higher than the limit you set, e.g. subMenuLimitA(12). However, if you are reducing encoderPos and it would naturally have decremented and wrapped around from 0 to 255, it won't go from 0 to 12. It will just stay at 0. If you want it to wrap around from 0 to 12 when decrementing, I'm sure you can play around with something to introduce that behaviour (similar may also be in my other instructible about menus but I can't remember).

    View Instructable »
  • Improved Arduino Rotary Encoder Reading

    Hi @djw4250, most encoders will run through all four states for one detent (click) - if I recall correctly. You appear to have an encoder which has one state change per detent. You could change your encoder or change the code. You could base your own code on my sketch or even the basic serial monitor sketch that you have implemented there as your test (which polls the pin). If the rest of your sketch will run through the loop() quickly, you would likely be able to poll without missing turns. Try something and let me know. Then we could move on to the 12 item limit.

    View Instructable »
  • Improved Arduino Rotary Encoder Reading

    Using your multimeter can you confirm that BOTH the encoder pins connect and disconnect at least once with the common pin when you turn one detent click? You'll have to do this one at a time, unless you have two multimeters.You could try reading each pin in the loop() next and printing out on your serial monitor what the status is, e.g. Serial.print(digitalRead(encoderPinA)); Serial.print("\t"); Serial.println(digitalRead(encoderPinB)); delay(10);This will print the logic state of the two encoder pins next to each other on a different line each time, separated by a tab ("\t").If you vary the delay duration you should be able to catch the logic on each pin if you scroll back up through the serial monitor print. Hopefully you'll see a progression like:11100001or the equi…

    see more »

    Using your multimeter can you confirm that BOTH the encoder pins connect and disconnect at least once with the common pin when you turn one detent click? You'll have to do this one at a time, unless you have two multimeters.You could try reading each pin in the loop() next and printing out on your serial monitor what the status is, e.g. Serial.print(digitalRead(encoderPinA)); Serial.print("\t"); Serial.println(digitalRead(encoderPinB)); delay(10);This will print the logic state of the two encoder pins next to each other on a different line each time, separated by a tab ("\t").If you vary the delay duration you should be able to catch the logic on each pin if you scroll back up through the serial monitor print. Hopefully you'll see a progression like:11100001or the equivalent for the other direction/wiring/print order.

    View Instructable »
  • Improved Arduino Rotary Encoder Reading

    I cannot explain why you see this behaviour. I may have a chance if you can tell me exactly how the internal and external wiring of your encoder is set up. I suspect that you may have an unusual connection setup. What microcontroller are you using?Yes, there is a way to control the number of menu items with a limit. See my other instructible on menus for rotary encoders for a start. Other people in the comments of these two instructibles have also asked and had some explanation, so go and have a look through the comments sections too, if you don't get what you're after from the main article.

    View Instructable »
  • Easy Arduino Menus for Rotary Encoders

    I don't know if this relates to the issues you observe but: 1) you don't appear to have any button debouncing in your main loop (although it is in the menu code, so can be copied from there or reused...), so you could be getting very confusing button input logic received by the microcontroller as a result. Here's my go-to for that: http://www.gammon.com.au/switches2) You only seem to call openMenu() if you press the button, and that is where the encoderPos printing/updating happens, so I don't know if that's an issue. The updating of your setting variables from the encoder should be allowed to continue even if the button isn't pressed, once you have entered the menu, no?3) You only seem to update the display when you enter the menu? But I haven't read it in more detail, just trying to giv…

    see more »

    I don't know if this relates to the issues you observe but: 1) you don't appear to have any button debouncing in your main loop (although it is in the menu code, so can be copied from there or reused...), so you could be getting very confusing button input logic received by the microcontroller as a result. Here's my go-to for that: http://www.gammon.com.au/switches2) You only seem to call openMenu() if you press the button, and that is where the encoderPos printing/updating happens, so I don't know if that's an issue. The updating of your setting variables from the encoder should be allowed to continue even if the button isn't pressed, once you have entered the menu, no?3) You only seem to update the display when you enter the menu? But I haven't read it in more detail, just trying to give ideas about where to look.4) Is your button logic consistent between the menu states? e.g. 0 is select in main loop, is that the same in e.g. the openMenu() function? Just wondering if it is entering an endless loop because of the state that variable leaves the functions in. Just some ideas - I apologise if they are not useful.

    View Instructable »
  • Easy Arduino Menus for Rotary Encoders

    Hi @Spa2036. It will be hard for anyone to help if you don't share details of your hardware setup or the exact code you're using. If you do post these, we might be able to replicate your issue and see what could solve it.

    View Instructable »
  • Improved Arduino Rotary Encoder Reading

    What's your hardware/software setup @Raplhxyz? Any differences to that detailed in the instructible (microcontroller/board, code, wiring)?

    Have you checked the baud rate on the serial monitor and the COM port is the same as the arduino? Is the serial monitor working correctly otherwise? If so, I think you may need your 5v line connected rather than relying on the pullup resistors on the arduino digital pins.

    Glad it worked for you!

    View Instructable »
  • Improved Arduino Rotary Encoder Reading

    Great news, any chance of you hosting/posting the code for others somewhere? I'd imagine STM32 is a more popular chip these days, for hobbyists, than when I published this instructible. So I'm sure others would like to see what you did.

    View Instructable »
  • Easy Arduino Menus for Rotary Encoders

    Hi Harry, you haven't given nearly enough information for someone to answer your question. Can you get sensible readings using the code in my other Instructible that doesn't have any menu code? If not, concentrate on sorting that first. Have you checked pins are correctly connected for your encoder and microcontroller? Are there external pull up or pull down resistors connected to the encoder, perhaps if it is mounted on a breakout board?

    View Instructable »
  • Do you want help with the rotary encoder part of the project? What specific challenge to do with rotary encoders would you like help with?

    Hi, the section of the Instructible that talks about codes portability is the hint that it won't work on many microcontrollers. I have not tried to port the code to the ESP32 but you may find some inspiration in JulekT's code that only needs one interrupt pin. Find an alternative way to digitally read the relevant pins simultaneously or in very quick succession and you will be on your way.

    View Instructable »
  • Yes, that detail was hidden in the text: "Note: In the diagram the ground pin is one of the end pins. In reality, the ground pin is often the centre pin but this is not always the case so read the datasheet or test your encoder to find out which pin is ground."

    View Instructable »
  • Sorry for the late reply. I haven't implemented this myself and don't plan to. I hope you found a way round.

    Good approach if you need the other hardware interrupt (eg if you want to use two encoders on an ATMEGA328PB)

    Sorry for the late reply. If you look in the code for the button press (non-delay type) you could start storing the millis() in variables. You can then compare when the button was pressed with the time it was released and then decide if you want to enter or exit or increment a mode.

    View Instructable »
  • Try the same modeMax approach in other modes as is used in Mode 0: if (encoderPos > (modeMax+10)) encoderPos = modeMax; // check we haven't gone out of bounds below 0 and correct if we have else if (encoderPos > modeMax) encoderPos = 0; // check we haven't gone out of bounds above modeMax and correct if we haveThis should limit the values that encoderPos can adopt. You will need to create different variable names for your limit (such as modeMax0, modeMax1 etc.

    View Instructable »
  • Thanks for letting me know this Instructable was useful to you - I owe much to people taking time to share knowledge online so it's good to know I'm giving back in a small way. I'm sure people would be interested in the teensy ported version, as well as some of your other features.

    View Instructable »
  • Glad to hear you worked it out! Thanks for letting us know your experience - I'm sure it'll help others.

    View Instructable »
  • Hi, that does sound like a voltage / pin connection issue from what you have mentioned. I would try other combinations of pin connections, perhaps with a physical indication of the pin voltage like a resistor and LED from the pin to ground in parallel with the signal lines.

    View Instructable »
  • In //Main menu section if (Mode == 0) {...try changing:if (buttonPressed){ Mode = encoderPos; // to:if (buttonPressed && encoderPos == 0) { // this will only let the button change the mode if the encoder is at zero Mode = (Mode+1) % 2 ; // this will alternate the mode between 0 and 1. Just increase 2to 3 to get three modes etc.Otherwise you'll need to post your code before people can help much more.

    I would look in rotaryMenu() and in the conditional statement if(oldEncPos != encoderPos) { // DEBUGGINGI would put further checks for which direction, such as:if(oldEncPos > encoderPos) keyboard.press "a";else keyboard.press "b";}then I would look in the "if buttonState == LOW" as you already have done to put the keyboard.press "c". Not sure why it's currently triggering when you press the button unless you are rotating the encoder as you press it.

    View Instructable »
  • If it's a message you don't want to put in the comments, I think you can send me a private message using your Instructables account.

    View Instructable »
  • Hi BlueM7, sorry I didn't get a notification for your comment. I haven't used this yet but I have bought something like this for my new jog controller https://m.banggood.com/100PPR-6-Terminal-Eletronic-Hand-Wheel-Manual-Pulse-Encoder-Generator-For-CNC-Machine-p-1121930.html?You may also like my approach to a jog controller https://hackaday.io/project/29627-grbl-man-in-the-middle-cnc-jog-pendant

    View Instructable »
  • This kind of advice often brings out valuable advice in the comments. Thanks to people who chip in but I'm not sure I'm much further ahead in terms of knowing how to look after my TS100 tips!

    View Instructable »
  • This is a great Instructable! So much for others to learn about what it is really like to try something you haven't done before. Thank you for sharing.

    View Instructable »
  • Hi MarcoM280, I would declare a further variable "encoderPosButton". Then, instead of:"if (reading == B00001100 && bFlag) { //check that we have both pins at detent (HIGH) and that we are expecting detent on this pin's rising edge encoderPos ++; //increment the encoder's position count"Use:"if (reading == B00001100 && aFlag) { //check that we have both pins at detent (HIGH) and that we are expecting detent on this pin's rising edge if (buttonPressed) encoderPosButton --; //decrement the encoder's button closed position count else encoderPos --; //decrement the encoder's button open position count"Then, you need to do the same changes to the encoderPos increment section:"if (reading == B00001100 && bFlag) { //check that we…

    see more »

    Hi MarcoM280, I would declare a further variable "encoderPosButton". Then, instead of:"if (reading == B00001100 && bFlag) { //check that we have both pins at detent (HIGH) and that we are expecting detent on this pin's rising edge encoderPos ++; //increment the encoder's position count"Use:"if (reading == B00001100 && aFlag) { //check that we have both pins at detent (HIGH) and that we are expecting detent on this pin's rising edge if (buttonPressed) encoderPosButton --; //decrement the encoder's button closed position count else encoderPos --; //decrement the encoder's button open position count"Then, you need to do the same changes to the encoderPos increment section:"if (reading == B00001100 && bFlag) { //check that we have both pins at detent (HIGH) and that we are expecting detent on this pin's rising edge if (buttonPressed) encoderPosButton ++; //increment the encoder's button closed position count else encoderPos ++; //increment the encoder's button open position count"You can get rid of most of the menu code as this only relies on the encoder reading BUT you need to keep the buttonPressed code! Good luck - I haven't tested this but it should help you get round your mental block!

    View Instructable »
  • Bullfrogerwytsch, glad you got it sorted and although I don't have an immediate application for your menu I'm sure it would be helpful for others. Please post in the comments! Thanks.

    Thanks 400 Hz! Good to keep people up to date. I'm going to leave the code in the Instructable the same for now but will consider changing it if people have issues.

    View Instructable »
  • Not specifically. You'd have to convert encoder position to an angle (perhaps use map() function), then compare the angle value to your limit/threshold (perhaps use if() function). Then you can do what you want to inside the if() function. You can do all that inside your loop () function.

    View Instructable »
  • TylerM173, can you explain what you're trying to achieve with a bit more detail and context? Are you talking about a 360 degree rotation of the encoder or just one detent? Or half to a quarter of a detent (as there are two zero phases and they overlap)?The code already adds/subtracts 1 to/from encoderPos if you rotate through the contacts for one detent. If you're talking about a full 360 rotation, you can just set an if() statement which resets the variable encoderPos to zero when it goes above the same number of detents per rotation.

    View Instructable »
  • Hi Pierre, thanks for taking the time to let people know how you are using the code. Ideas of the possible applications are always useful, especially when someone can confirm it's feasible. The code in the my Instructables uses some language elements that are specific to the ATMEGA328P (which is why you need different code for the MEGA2561). You might be able to spot how to adapt the external interrupts to work with the Wemos D1 mini from this blog post https://techtutorialsx.com/2016/12/11/esp8266-external-interrupts/Please come back and tell us how you get on.

    View Instructable »
  • kd6oji, I'm not sure how to put this into a library. Can't you just use the clickbutton library from https://github.com/pkourany/clickButton/tree/master/src and keep the encoder code in the main sketch?

    View Instructable »
  • Vacuum Pump From Aquarium Air Pump

    Random_Canadian thank you for this Instructable! I want to make a vacuum pickup tool for an OpenPNP machine and tried to copy this Instructable exactly. I couldn't buy a "Whisper 100" model but did buy the Tetra APS 100 (designed for 50-100 litre tanks). It has a single diaphragm and outlet so it may turn out to be undersized for other people looking to buy a similar pump for an SMT part pickup application.I found the (single) white plastic part quite difficult to slide out before I could rotate it and reverse the valves to create a vacuum. I was worried that I'd break something if I forced the white plastic up and out of its slot because the design didn't exactly match the photos in this Instructable. However, I can confirm that a right angle hex key levered it out intact, with…

    see more »

    Random_Canadian thank you for this Instructable! I want to make a vacuum pickup tool for an OpenPNP machine and tried to copy this Instructable exactly. I couldn't buy a "Whisper 100" model but did buy the Tetra APS 100 (designed for 50-100 litre tanks). It has a single diaphragm and outlet so it may turn out to be undersized for other people looking to buy a similar pump for an SMT part pickup application.I found the (single) white plastic part quite difficult to slide out before I could rotate it and reverse the valves to create a vacuum. I was worried that I'd break something if I forced the white plastic up and out of its slot because the design didn't exactly match the photos in this Instructable. However, I can confirm that a right angle hex key levered it out intact, without any damage, from under the bottom face of the white plastic square flange.I then rotated the square and replaced it. When I turned it on I felt the vacuum and it seems like it could hold small SMT parts but that will need testing. When I put my finger over the outlet, the diaphragm inside got pulled in by the vacuum and this caused the magnetic pump head to hit the plastic inside the casing. It was now a very noisy vacuum pump! See the yellow circle and arrow in the attached photo to see where the impact occurs.I have heard this noise when watching YouTube videos of DIY pick and place machines, and now I know where it comes from. As I now understood the problem, I wanted to reduce the noise, as it would clearly be the most noisy part of an OpenPNP DIY machine and I didn't want to be annoyed during its operation.To solve the problem, I added a spring from a ballpoint pen between the housing and the pump arm and held it in place with hot glue. See the light blue outline in the attached photo to see the arrangement I used. The pump is now quieter when I put my finger over the outlet (now the inlet, I suppose!) than when it is free running against no pressure. I'm very happy and hope these extra details help others get what they want from these great little devices.

    View Instructable »
  • kd6oji, that's encouraging to hear and thanks for taking the time to let us know!

    View Instructable »
  • Hi coffs, sorry I didn't reply earlier. I haven't tried this but I believe it is possible to set up sub menus by placing one in each setting. It would lead to significantly more case/switch code unless you can modularise it.

    View Instructable »
  • My electronics knowledge isn't great but you might be able to reduce the workload for the processor using an op amp as a comparator and/or (!) some logic gates. Perhaps some latching would be required. I'm not working on anything like this but if you find something, please post a link!

    View Instructable »
  • Bryan, from what you've said I believe the Uno is absolutely capable of meeting your needs. Just use a Pin Change Interrupt (as per the Nick Gammon guide I linked to in my other reply) for the Z reset. You can use a display with an I2C or SPI interface if you want or set up a software serial pair of Rx/Tx pins to talk to another device (but I would like to think your further calculations can be done on the first Uno). Depending on your display interface, that will steer you to what pins remain for your Pin Change Interrupt. Keep at it. Even if you decide to order a Mega 2560, try the pin change interrupt on the Uno while you're waiting. You can even get a neopixel ring of colour changing leds and use those to display the angle of the encoder readout. That would only require one digital pi…

    see more »

    Bryan, from what you've said I believe the Uno is absolutely capable of meeting your needs. Just use a Pin Change Interrupt (as per the Nick Gammon guide I linked to in my other reply) for the Z reset. You can use a display with an I2C or SPI interface if you want or set up a software serial pair of Rx/Tx pins to talk to another device (but I would like to think your further calculations can be done on the first Uno). Depending on your display interface, that will steer you to what pins remain for your Pin Change Interrupt. Keep at it. Even if you decide to order a Mega 2560, try the pin change interrupt on the Uno while you're waiting. You can even get a neopixel ring of colour changing leds and use those to display the angle of the encoder readout. That would only require one digital pin as well as power and ground. There's loads of guidance on neopixel and arduino on the Internet. Keep going!

    View Instructable »
  • Hi Bryan, thanks for posting in the comments. Before we get to your main issue, I want to say you've done a good job changing encoderPos to a larger size than a Byte but you might also want to change oldEncoderPos in the same way. So, the problem is that you are trying to put a hardware interrupt on a pin which doesn't support it (digital pin 4). Only pins 2 and 3 support the kind of interrupt code we've used here. However, you can add pin change interrupts to the other pins (beware that it involves a whole port and therefore up to 8 pins - suggest you may want to look at using the analog pins if you want to reserve pin 13 as your LED pin. The best guide I know to all kinds of interrupts is by Nick Gammon (who is attributed in my code) and his section on pin change interrupts is here - go…

    see more »

    Hi Bryan, thanks for posting in the comments. Before we get to your main issue, I want to say you've done a good job changing encoderPos to a larger size than a Byte but you might also want to change oldEncoderPos in the same way. So, the problem is that you are trying to put a hardware interrupt on a pin which doesn't support it (digital pin 4). Only pins 2 and 3 support the kind of interrupt code we've used here. However, you can add pin change interrupts to the other pins (beware that it involves a whole port and therefore up to 8 pins - suggest you may want to look at using the analog pins if you want to reserve pin 13 as your LED pin. The best guide I know to all kinds of interrupts is by Nick Gammon (who is attributed in my code) and his section on pin change interrupts is here - good luck: http://gammon.com.au/forum/?id=11488&reply=6#reply6

    View Instructable »
  • Glad it made sense - looking back it wasn't the clearest explanation!

    View Instructable »
  • "B" means a binary number (Google if you want further explanation). The list of 1s and 0s after is a list of bits that make up a Byte. Each bit represents a pin on the microcontroller. The pins are grouped into "ports" which each have 8 pins, so a single binary Byte can represent the digital state of a whole port. To use code that commands the ports (called port manipulation), you have to find which port pins 20 and 21 etc are on. Eg they are on Port D. 21 is PD0, 20 is PD1 (goes in reverse). So in the byte which describes the whole of PortD, they are B000000(20)(21). Google for a "atmega 2560 pinout diagram" to check the pin assignment to ports if you don't want to look at the datasheet (which I do recommend). Then change the code which relates to port manip…

    see more »

    "B" means a binary number (Google if you want further explanation). The list of 1s and 0s after is a list of bits that make up a Byte. Each bit represents a pin on the microcontroller. The pins are grouped into "ports" which each have 8 pins, so a single binary Byte can represent the digital state of a whole port. To use code that commands the ports (called port manipulation), you have to find which port pins 20 and 21 etc are on. Eg they are on Port D. 21 is PD0, 20 is PD1 (goes in reverse). So in the byte which describes the whole of PortD, they are B000000(20)(21). Google for a "atmega 2560 pinout diagram" to check the pin assignment to ports if you don't want to look at the datasheet (which I do recommend). Then change the code which relates to port manipulation (B000XXXX, PIN(Y), PORT(Z) etc).

    View Instructable »
  • Hi Nurochim, this has been asked and answered partly in the comments below and the comments for my menu instructable. If you're a newbie and you want to make this work, you have a little bit of learning to do but that's great if you're doing this for a school project.Here's the text from some relevant comments. You might need the datasheet for the ATMEGA2560 and/or a port manipulation guide and pinouts for the ATMEGA2560:"Hi, I haven't tested this but I expect the reason it doesn't work directly with the mega2560 is because the interrupt service routine relies on port manipulation and the mega2560's hardware interrupt pins aren't on the same ports as the atmega328. My code above could be easily adapted for the mega2560 if you change PIND to the correct port, eg PINE, to read port E. …

    see more »

    Hi Nurochim, this has been asked and answered partly in the comments below and the comments for my menu instructable. If you're a newbie and you want to make this work, you have a little bit of learning to do but that's great if you're doing this for a school project.Here's the text from some relevant comments. You might need the datasheet for the ATMEGA2560 and/or a port manipulation guide and pinouts for the ATMEGA2560:"Hi, I haven't tested this but I expect the reason it doesn't work directly with the mega2560 is because the interrupt service routine relies on port manipulation and the mega2560's hardware interrupt pins aren't on the same ports as the atmega328. My code above could be easily adapted for the mega2560 if you change PIND to the correct port, eg PINE, to read port E. It looks like arduino interrupt pins are on 2 and 3, which appears to equate to PE4 and PE5. That means you also need to change the B0000XX00 to bit shifting/ masking/ comparing B00XX0000 (PE0 will be the right hand bit, PE7 will be the left hand bit) to deal with the readings from your encoder. Good luck with the edit - I think it's definitely doable. Please post the code you change once you get it working so other people can use this on the mega2560""Suppeschluerfer SimonM83Reply9 months agoMega 2560 - Pin 2(INT0) and 3(INT1):PIND & 0xC change to PINE & 0x30B00001100 change to B00110000B00000100 change to B00010000B00001000 change to B00100000"

    View Instructable »
  • Hi alfabcd6, if you look at the code you can see modeMax and this sets the maximum value of the main menu. It sounds like you want to set the maximum value of your submenus. If so, you can add in modeMax1, modeMax2, modeMax3 etc. Then, in each case also include the modeMax code, as in: if(encoderPos > modeMax1+10){encoderPos = modeMax1};and:if(encoderPos > modeMax1) {encoderPos = 0};and then do that for each submenu. I hope that helps - let me know.

    View Instructable »
  • nathan2484, well done for coming up with a solution! Just for interest and in case you hadn't understood the cause of the number rolling over, if you look at the code, we declared the variable "encoderPos" as a byte. This just rolls over to 0 (or, in binary, 00000000) when you add 1 to 11111111 (ie 255) because if it were to be a 9 bit (as opposed to 8 bit) number it would tick over to 256 = 100000000. The 8 bit (1 byte) variable just ignores the 9th bit, reading from right to left, so we get back to 0. I hope I have explained that clearly enough. Using an "if" statement is a good way to control the upper and lower values of your encoderPos variable. Thanks for your kind gratitude.

    View Instructable »
  • Ralphxyz, I'm scratching my head on this one, as it's a directional issue that is at the encoder rather than the Arduino. Is there a chance that you have connected the wrong wire to Ground? Can you try different combinations of wiring?

    Amazing! I was just trying to think what to try next when I saw that you solved it. Well done!

    View Instructable »
  • Ralphxyz, does this stay the same if you swap your wires around?

    View Instructable »
  • SiDawg, glad to hear it's helped you and thanks for contributing to the community by posting your own findings.

    RonVZ, I'm sorry I missed your comment. The code is specific to the two inputs as-written but I see no reason why you can't add a second encoder. You will need to add the extra interrupts and write the Interrupt Service Routine to read and process the Port reading relevant to the new encoder input pins. You should be able to get a clue about the microcontroller's handling of the bit-math by looking at the comments in the existing ISR code. Good luck and I hope this is still helpful.

    View Instructable »
  • Sorry, I got confused when I commented that other people had addressed the 2560 in these comments - actually it was in the comments on my rotary encoder menu instructable. Check out this awesome Instructable. https://www.instructables.com/id/Easy-Arduino-Menus-for-Rotary-EncodersIf you scroll down to the comment by Suppeschluerfer there are suggestions for port (code) and pin settings on the 2560. I haven't tested it yet so it would be great if you could confirm if it worked.

    View Instructable »
  • Ron, please tell me you haven't selected your downloads folder as the default place to save Arduino sketches? The file path in the error message suggests it is trying to look there. Anyway, a few more things to try:1) try installing version 1.0.5 of the Arduino IDE - I know I can compile and upload to SSD1306 OLEDs from that version.2) in the file naming, make sure you remove the hyphens and master and number suffixes, so "Adafruit_SSD1306-master-6" folder would become "Adafruit_SSD1306". Make sure this is the version in your legitimate Arduino libraries folder, not something you unzipped into the downloads folder.3) always restart the IDE if you make changes to the libraries or the folders containing them.4) in the screenshot of your folder system, you appear to have …

    see more »

    Ron, please tell me you haven't selected your downloads folder as the default place to save Arduino sketches? The file path in the error message suggests it is trying to look there. Anyway, a few more things to try:1) try installing version 1.0.5 of the Arduino IDE - I know I can compile and upload to SSD1306 OLEDs from that version.2) in the file naming, make sure you remove the hyphens and master and number suffixes, so "Adafruit_SSD1306-master-6" folder would become "Adafruit_SSD1306". Make sure this is the version in your legitimate Arduino libraries folder, not something you unzipped into the downloads folder.3) always restart the IDE if you make changes to the libraries or the folders containing them.4) in the screenshot of your folder system, you appear to have moved the files Adafruit_GFX.cpp and Adafruit_GFX.h out of the Adafruit_GFX folder and into the Adafruit_SSD1306 folder. Move these two files back to the Adafruit_GFX folder.5) once in IDE version 1.0.5, open File/Examples/Adafruit_SSD1306 and then the SPI version of the 128x64 OLED (I presume you haven't modified the OLED PCB traces for I2C communication protocol instead of the default SPI protocol it should have arrived set up for? You'd have had to solder something to change this.). Try compiling now, having opened the example sketch from the IDE Examples section NOT by File/Open or by double clicking the sketch file from somewhere like the downloads folder in your file explorer (or Mac equivalent).Keep going!

    Ron, it sounds like you're trying to bite off a pretty challenging project for the level of skill you appear to have in this area. Even switching from LCD to OLED between your two comments would mean different technologies that have different driver chips and need different code to communicate with them.Let's try getting the OLED working. I don't use Mac, so some bits may be specific to the OS. What adafruit product do you have? Can you post a link? Have you searched for other people having and solving issues with connecting to it? Someone might have a much better ready-made answer already on the arduino or other forum than I could come up with. If you've managed to download the relevant libraries and install them correctly in the arduino IDE, I assume you've opened an example sketch for …

    see more »

    Ron, it sounds like you're trying to bite off a pretty challenging project for the level of skill you appear to have in this area. Even switching from LCD to OLED between your two comments would mean different technologies that have different driver chips and need different code to communicate with them.Let's try getting the OLED working. I don't use Mac, so some bits may be specific to the OS. What adafruit product do you have? Can you post a link? Have you searched for other people having and solving issues with connecting to it? Someone might have a much better ready-made answer already on the arduino or other forum than I could come up with. If you've managed to download the relevant libraries and install them correctly in the arduino IDE, I assume you've opened an example sketch for the display. Do you have the correct Arduino board selected in the IDE when you compile? It's a long shot but perhaps worth checking. Which Arduino are you using? You'll need to post much more information before people can help you get further with this. I'd recommend setting up an Arduino forum thread on this issue if you can't find a similar one that has already been started.

    Ron, it's a good sign that you have the other sketches working (I presume other than blink, which comes preloaded?).When you went and installed the SSD1306 and GFX libraries, did you follow these instructions from adafruit:Rename the uncompressed folder Adafruit_SSD1306 and check that the Adafruit_SSD1306 folder contains Adafruit_SSD1306.cpp and Adafruit_SSD1306.hPlace the Adafruit_SSD1306 library folder your arduinosketchfolder/libraries/ folder. You may need to create the libraries subfolder if its your first library. Restart the IDE.We also have a great tutorial on Arduino library installation at:http://learn.adafruit.com/adafruit-all-about-arduino-libraries-install-useBecause that's pretty fundamental during compilation. Do you know if you have a libraries folder in the place where yo…

    see more »

    Ron, it's a good sign that you have the other sketches working (I presume other than blink, which comes preloaded?).When you went and installed the SSD1306 and GFX libraries, did you follow these instructions from adafruit:Rename the uncompressed folder Adafruit_SSD1306 and check that the Adafruit_SSD1306 folder contains Adafruit_SSD1306.cpp and Adafruit_SSD1306.hPlace the Adafruit_SSD1306 library folder your arduinosketchfolder/libraries/ folder. You may need to create the libraries subfolder if its your first library. Restart the IDE.We also have a great tutorial on Arduino library installation at:http://learn.adafruit.com/adafruit-all-about-arduino-libraries-install-useBecause that's pretty fundamental during compilation. Do you know if you have a libraries folder in the place where you usually save sketches (try Save As on the blink sketch and see if you can see a libraries folder when it opens up the default location. If not, follow the libraries advice in the adafruit link.Good move including the screenshot. In Arduino IDE can you go to File/Preferences and tick the box for verbose output during compile? Then try and compile again (which should spit out lots more detailed text at the bottom of the screen) and press the button to the right of the orange error message bar which says "Copy error messages" and then Google that text to see if you have a common problem, paste it here and use it in any Arduino forum thread you write on.

    Hi Ron, here are the sections of code which refer to the push button/switch that represents a "select" input from the user:const byte buttonPin = 4; // this is the Arduino pin we are connecting the push button tovoid rotaryMenu() { ......// Button reading with non-delay() debounce - thank you Nick Gammon! byte buttonState = digitalRead (buttonPin);... (then the following logic in the rest of the rotaryMenu function)If you want to use the lcd, you need to put some code in that displays what you want, when you want. The code I've suggested isn't for an lcd, it uses the computer screen to display text in the Arduino IDE's serial monitor window when the Arduino is connected to the computer. If you look at the comments from TheMariuzaz below and my responses to them, you should see …

    see more »

    Hi Ron, here are the sections of code which refer to the push button/switch that represents a "select" input from the user:const byte buttonPin = 4; // this is the Arduino pin we are connecting the push button tovoid rotaryMenu() { ......// Button reading with non-delay() debounce - thank you Nick Gammon! byte buttonState = digitalRead (buttonPin);... (then the following logic in the rest of the rotaryMenu function)If you want to use the lcd, you need to put some code in that displays what you want, when you want. The code I've suggested isn't for an lcd, it uses the computer screen to display text in the Arduino IDE's serial monitor window when the Arduino is connected to the computer. If you look at the comments from TheMariuzaz below and my responses to them, you should see what I mean by some code to make the lcd display something. The adafruit tutorial for your lcd should give you the correct kind of code to use.

    View Instructable »
  • Is any of the data on the USB stick encrypted at rest by VSFTPD? Ie if I remove the USB drive can I easily read what it contains? Tried looking for an answer elsewhere but search results focused on the security of data in transit, not on the hard drive. Thanks, Simon

    View Instructable »
  • TheMariuzaz I'm glad it worked - I'm not sure I helped at all but it's great that you worked things through!

    View Instructable »
  • Are you saying you still have the same problem? I don't know if this is an issue but:if(setting1 <0){is confusing me. Are you supposed to check if a value is LESS than zero in your program?

    I'm struggling to see where your code fits into mine from the pastebin link. if (setting1 > 0) { lcd.setCursor(0,1); lcd.write(" "); lcd.setCursor(11,1); lcd.write((uint8_t)0); } Should it be:if (setting1 > 0) { lcd.setCursor(0,1); lcd.write(" "); lcd.setCursor(11,1); lcd.write((uint8_t)setting1); } ? It seems like both conditions of setting1 =0 OR setting1 > 0 lead to the lcd displaying 0.

    View Instructable »
  • Have you tried putting an lcd update term in place of every Serial.println() and Serial.print()?

    View Instructable »
  • Thanks for the simplifications. This is where a github repository would come in handy! Anyone with an account care to commit this code? Sorry to hear about your encoders. I think the ones I tested with were no-name eBay specials so that's surprising. No joy if you change the debounce time?

    View Instructable »
  • Glad to hear it's useful. The button reading part is all Nick Gammon's - he's got a great website full of useful information, especially about atmega328p arduinos.

    View Instructable »
  • That's a shame - I thought my encoder I used to test the system was a cheap one even though it was advertised as something better.

    View Instructable »
  • Githyuk, thanks so much for the update - that's the kind of thing that will really help someone else who may be losing patience. I have edited the Instructable in Step 2 and signposted them to the details in your comments. So glad it's working well for you now!

    Sorry, what I meant by branded was that it was a known part and therefore results should be repeatable (versus an unbranded eBay special). You're right to isolate the issue to the detent per pulse (although I'm not clear if it's 2 pulses per detent on the kind of encoder which works or 2 detents per pulse). Please show us the final results of your project.

    View Instructable »
  • I think there are three ways I'd try initially. First, for periodic updates you could use a non-blocking timer such as the method used in "blink without delay" sketches and the button press debouncing code I used in this (Nick Gammon's). Just put the if(millis() - delay > lastTime) type of statement in the main loop. Second, you can just add your "read temp, display temp" code in each of the if (Mode == X) statements for VERY frequent updates. Thirdly, if you can wait for temp to update only when you press the select button, place your "read temp, display temp" code in the setAdmin function. My preference would be the first option. Let us know how you get on.

    View Instructable »
  • Hmm, I used an Alps EC11B0924802 but I think the logic is all the same apart from whether the pins are grounded or not at detent. You might want to look at whether your reset is around B00001100 or B00000000. Other than that, I wonder if the capacitor is preventing the pin from reaching a 0 in sufficient time but I can't think what situation this could realistically occur in. Try without caps perhaps? Does it work in the same direction if you swap the arduino pins over?

    View Instructable »
  • Hi Githyuk, sorry it's not working yet. Can you confirm that this behaviour is the same at low rotation speed? This would help rule out contact bounce. You could add some hardware debouncing to be sure. From not knowing much about your setup (although encoder datasheet link was a good idea), I think there might be a situation where the other pin is always high when the other one triggers the interrupt. E.g, if you read B00001000, then you can get B00001100 but never B00000100 or B00000000. If this is the case, it could be a short circuit on the wiring to the pin, pulling it HIGH, or it could perhaps be that one of the Arduino pins is connected to the encoder ground pin. The data sheet didn't seem to be clear about which pins are A, B and ground (although it would be a good first assumptio…

    see more »

    Hi Githyuk, sorry it's not working yet. Can you confirm that this behaviour is the same at low rotation speed? This would help rule out contact bounce. You could add some hardware debouncing to be sure. From not knowing much about your setup (although encoder datasheet link was a good idea), I think there might be a situation where the other pin is always high when the other one triggers the interrupt. E.g, if you read B00001000, then you can get B00001100 but never B00000100 or B00000000. If this is the case, it could be a short circuit on the wiring to the pin, pulling it HIGH, or it could perhaps be that one of the Arduino pins is connected to the encoder ground pin. The data sheet didn't seem to be clear about which pins are A, B and ground (although it would be a good first assumption that a = A, b =B and c = ground. Perhaps check the wiring for pull-up short circuits and the try different combinations of encoder wiring. Hope that helps - post pictures if you have no joy.

    View Instructable »