My goal is to create a small switch panel for my Windows 10 PC. I'm using an Arduino Micro to run my program. I want to use a digital rotary encoder to control Joystick inputs. I want to control volume by pressing volume up when I turn the encoder clockwise, and volume down when I turn it counterclockwise
#include <Joystick.h>
#define outputA 2
#define outputB 3
int counter = 0;
int aState;
int aLastState;
void setup() {
Joystick.begin();
pinMode(2, INPUT);
pinMode(3, INPUT);
}
void loop() {
aState = digitalRead(outputA);
if (aState != aLastState) {
if (digitalRead(outputB) != aState) { // Clockwise
Joystick.pressButton(1);
delay(10);
Joystick.releaseButton(1);
counter ++;
} else { // Counterclockwise
Joystick.pressButton(2);
delay(10);
Joystick.releaseButton(2);
counter --;
}
Serial.print("Counter: ");
Serial.println(counter);
}
aLastState = aState;
}
This should press a button (button 1) every time the pins are pushed clockwise, and press button 2 when they are moving counterclockwise. I have tried to make the counter value print out to the serial monitor to see what it was doing, but the monitor changes at random moments and doesn't recognize the rotary encoder. I can clarify any points of this, but I was wondering what I could fix.
It turns out that this was just an interference issue. Using pullup resistors fixed the problem.
Related
Recently I have been working on a project where the main goal is to move a servo on a model rocket to deploy a parachute. I want to make is so that 10 seconds after I press the button the parachute is released. I have some code for this already but It is not working, as it stops the code completely. Does anyone know how to fix this?
#include <Servo.h>
// constants won't change
const int BUTTON_PIN = 7; // Arduino pin connected to button's pin
const int SERVO_PIN = 9; // Arduino pin connected to servo motor's pin
Servo servo; // create servo object to control a servo
// variables will change:
int angle = 0; // the current angle of servo motor
int lastButtonState; // the previous state of button
int currentButtonState; // the current state of button
void setup() {
Serial.begin(9600); // initialize serial
pinMode(BUTTON_PIN, INPUT_PULLUP); // set arduino pin to input pull-up mode
servo.attach(SERVO_PIN); // attaches the servo on pin 9 to the servo object
servo.write(angle);
currentButtonState = digitalRead(BUTTON_PIN);
}
void loop() {
lastButtonState = currentButtonState; // save the last state
currentButtonState = digitalRead(BUTTON_PIN); // read new state
if(lastButtonState == HIGH && currentButtonState == LOW) {
Serial.println("The button is pressed");
time.delay(10000)
// change angle of servo motor
if(angle == 0)
angle = 90;
else
if(angle == 90)
angle = 0;
// control servo motor arccoding to the angle
servo.write(angle);
}
}
In Arduino, a delay is usually done with delay(10000); (for 10 seconds). I've never seen or heard of the time.delay() function, so that might be the issue. Otherwise the code looks like it should work as you want.
It also might depend on the board you're running it on. I remember having issues using delay() for long periods on an ESP8266 although I'm pretty sure that it is fine for tens of seconds.
I'm a newbie to Arduino. The goal is to write a program that can stop a hypothetical conveyor belt (read a servo motor) if too many objects are stacked on a belt, that is detected by HC-S04 sensor. If the the distance exceeds the minimum threshold value (1000), then the motor can freely spin. If not, it should stop. With the code below, I get a servo motor to spin regardless of whether an object is in front of it or not.
Tried taking out and changing the delay. It just was spinning faster or slower, but still ignored obstacle distance. Tried commenting sensorValue = map(sensorValue, 0, 255, 0, 4000); but it didn't affect the result.
#include <Servo.h>
#include <Wire.h>
Servo servo;
const int trigPin= 9;
const int echoPin= 10;
const int threshold = 1000;
void setup() {
pinMode(trigPin, OUTPUT);
pinMode(echoPin,INPUT);
Serial.begin(9600);
servo.attach(8);
}
void loop() {
int sensorValue = digitalRead(echoPin);
sensorValue = map(sensorValue, 0, 255, 0, 4000);
if (sensorValue >= threshold) {
digitalWrite(8,HIGH);
delay(10);
}
else {
digitalWrite(8,LOW);
delay(10);
}
}
Debug by outputting your sensorValue contents - this will allow you to check which branch is triggered.
(can't post as a comment because my rep is not high enough).
You can use the debugging values to check, configure and calibrate your sensor.
I'm back with another non-homework related question. I'm playing with an arduino with my brother, and we're trying to attach a button so that when its pressed, his sensor stays on and does what it has to do. When its pressed again it'll do nothing and turn off. Right now when the button is held down it stays on, but when its unpressed it stays off. We're trying to make something that'll continuously take pictures when its thrown off a building. It'll stop with the ultra-sonic sensor reads <= 5. I can't throw myself off the roof top while holding the button XD It's a 2 pin button. Here's the code of what we have right now:
// defines pins numbers
const int trigPin = 9;
const int echoPin = 10;
const int buzzer = 11;
const int ledPin = 13;
const int buttonPin = 2;
// defines variables
long duration;
int distance;
int safetyDistance;
#include <Servo.h>
Servo myservo; // create servo object to control a servo
// twelve servo objects can be created on most boards
int pos = 0; // variable to store the servo position
void setup() {
pinMode(echoPin, INPUT);// Sets the echoPin as an Input
pinMode(buttonPin, INPUT);
pinMode(trigPin, OUTPUT); // Sets the trigPin as an Output
pinMode(buzzer, OUTPUT);
pinMode(ledPin, OUTPUT);
Serial.begin(9600); // Starts the serial communication
myservo.attach(8); // attaches the servo on pin 9 to the servo object
}
void loop() {
// Clears the trigPin
digitalWrite(trigPin, LOW);
delayMicroseconds(2);
digitalWrite(buttonPin, HIGH);
// Sets the trigPin on HIGH state for 10 micro seconds
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
// Reads the echoPin, returns the sound wave travel time in microseconds
duration = pulseIn(echoPin, HIGH);
// Calculating the distance
distance= duration*0.034/2;
safetyDistance = distance;
if (digitalRead(buttonPin) == HIGH)
{
if (safetyDistance <= 5){
digitalWrite(buzzer, HIGH);
digitalWrite(ledPin, HIGH);
}
else{
digitalWrite(buzzer, LOW);
digitalWrite(ledPin, LOW);
for(pos = 0; pos <= 180; pos += 20) // goes from 0 degrees to 180 degrees
{ // in steps of 1 degree
myservo.write(pos); // tell servo to go to position in variable 'pos'
delay(10); // waits 15ms for the servo to reach the position
}
for(pos = 180; pos>=0; pos-=2) // goes from 180 degrees to 0 degrees
{
myservo.write(pos); // tell servo to go to position in variable 'pos'
delay(10); // waits 15ms for the servo to reach the position
}
}
}
// Prints the distance on the Serial Monitor
Serial.print("Distance: ");
Serial.println(distance);
}
Now, what we're having trouble with is, I understand that there has to be states for the button. But as we were scouring the internet for help we came across terms like debouncing and we just don't understand what that means. We're so close to finally finishing our mini project. The servo is moving fine, the ultrasonic sensor works well. We just need help figuring out this button. Any advice and help would be appreciated as we're both scratching our heads on this one. Thank you!!
--Zane
Normal buttons, like they are used in most project, are doing nothing else but pressing two electrical contacts together, when it is pressed. But - because it's a mechanical action with limited velocity - the level on the pin doesn't simply rise from LOW to HIGH (or vice versa). Instead it changes it's level in the moment the button gets pressed a few times, until the final level is reached. This variation is to fast for a human to see (for example with an attached LED), but slow enough for a microcontroller like the arduino taking notice. So often you have to make sure, that it's really only one button press, even if the level changes a few times in a row. Mostly it is sufficient to add a small timeout, where the button presses aren't recognized by your code (for example 50 ms), or checking a second time for the state of the button after this period. You can check the corresponding Arduino page for an official example of debouncing.
In your code you are only checking directly the state of the button, which is why it turns off, when you release the button. I would try something like this:
boolean program_state = false;
unsigned long debounce_time = 50;
unsigned long debounce_time_stamp=0;
void loop(){
// ultasound measuring code
if(digitalRead(buttonPin) && debounce_time_stamp - millis() > debounce_time){
program_state=!program_state;
debounce_time_stamp = millis();
}
if(program_state){
// distance checking and servo code
}
}
This check - when the button is pressed - if enough time has been bygone since the last recognized press (the amount of time can be adjusted with the variable debounce_time). When a valid press is recognized, the program_state variable is toggled to change the state between the two modes (On and Off).
Notice that with this the code is unresponsive for the time the servo needs to finish one sequence. If you want to have code, that is more responsive, you should consider using the button as an external interrupt (for this look at the examples on the correspondig Arduino page).
I want to use Arduino to control a stepper motor and catch the feedback. After my upper computer catch the feedback there is other work to do after the stepper motor has rotated. The code is as below:
int x;
void setup() {
Serial.begin(9600);
pinMode(5,OUTPUT); // Step
pinMode(4,OUTPUT); // Dir
}
void loop() {
digitalWrite(4,LOW);
for(x = 0; x < 3200; x++) // Loop 3200 times
{
digitalWrite(5,HIGH); // Output high
delayMicroseconds(400);
digitalWrite(5,LOW); // Output low
delayMicroseconds(400);
}
Serial.println("ok");
delay(1000);
}
But before the stepper motor rotate, the upper computer has already received the feedback of "ok". How can I improve my code.
Lets say I have 4 images and I want to use these 4 images to animate a character. The 4 images represent the character walking. I want the animation to repeat itself as long as I press the key to move but to stop right when I unpress it. It doesn't need to be SFML specific if you don't know it, just basic theory would really help me.
Thank you.
You may want some simple kind of state machine. When the key is down (see sf::Input's IsKeyDown method), have the character in the "animated" state. When the key is not down, have the character in "not animated" state. Of course, you could always skip having this "state" and just do what I mention below (depending on exactly what you're doing).
Then, if the character is in the "animated" state, get the next "image" (see the next paragraph for more details on that). For example, if you have your images stored in a simple 4 element array, the next image would be at (currentIndex + 1) % ARRAY_SIZE. Depending on what you are doing, you may want to store your image frames in a more sophisticated data structure. If the character is not in the "animated" state, then you wouldn't do any updating here.
If your "4 images" are within the same image file, you can use the sf::Sprite's SetSubRect method to change the portion of the image displayed. If you actually have 4 different images, then you probably would need to use the sf::Sprite's SetImage method to switch the images out.
How would you enforce a framerate so that the animation doesn't happen too quickly?
Hello please see my answer here and accept this post as the best solution.
https://stackoverflow.com/a/52656103/3624674
You need to supply duration per frame and have the total progress be used to step through to the frame.
In the Animation source file do
class Animation {
std::vector<Frame> frames;
double totalLength;
double totalProgress;
sf::Sprite *target;
public:
Animation(sf::Sprite& target) {
this->target = ⌖
totalProgress = 0.0;
}
void addFrame(Frame& frame) {
frames.push_back(std::move(frame));
totalLength += frame.duration;
}
void update(double elapsed) {
// increase the total progress of the animation
totalProgress += elapsed;
// use this progress as a counter. Final frame at progress <= 0
double progress = totalProgress;
for(auto frame : frames) {
progress -= (*frame).duration;
// When progress is <= 0 or we are on the last frame in the list, stop
if (progress <= 0.0 || &(*frame) == &frames.back())
{
target->setTextureRect((*frame).rect);
break; // we found our frame
}
}
};
To stop when you unpress, simply only animate when the key is held
if(isKeyPressed) {
animation.update(elapsed);
}
To support multiple animations for different situations have a boolean for each state
bool isWalking, isJumping, isAttacking;
...
if(isJumping && !isWalking && !isAttacking) {
jumpAnimation.update(elapsed);
} else if(isWalking && !isAttacking) {
walkAnimation.update(elapsed);
} else if(isAttacking) {
attackAnimation.update(elapsed);
}
...
// now check for keyboard presses
if(jumpkeyPressed) { isJumping = true; } else { isJumping false; }