Arduino-uno project [closed] - arduino-uno

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I'm currently working with an Raspberry Pi for a exercise.
I'm working with the following on the breadboard:
5 LED's
2 Switches
My following code is supposed to work as follows:
With the first button you can select the next LED and with the second button you can put the selected LED on/off. When you're at the last LED it gives a true or a false (on or off) with the following output:
Circuits
I don't see what's wrong with my code:
//const variables
const int leds[] = {3, 5, 6, 9, 11};
const int buttons[] = {12, 13};
//variables that will change
int buttonState[] = {false, false};
int lastButtonState[] = {false, false};
int values[] = {false, false, false, false};
void setup() {
//init LEDs
for(int i = 0; i < sizeof(leds); i++){
pinMode(leds[i], OUTPUT);
}
//init buttons
for(int i = 0; i < sizeof(buttons); i++){
pinMode(buttons[i], INPUT);
}
}
void loop() {
//fade when game starts
fade();
//start game
start();
//output of game
output();
}
void output(){
bool t1 = !values[0];
bool t2 = t1 && values[1];
bool t3 = values[2] || values[3];
bool Q = !(t2 || t3);
if(!Q){
digitalWrite(leds[4], true);
}else{
digitalWrite(leds[4], false);
}
}
void start(){
//total of leds
int j = 0;
//check if user is not at 5th led
while(j < 4){
//loop through buttons
for(int i = 0; i < 2; i++){
// Read button
buttonState[i] = digitalRead(buttons[i]);
// check button state
if (buttonState[i] != lastButtonState[i]) {
// if the state has changed
if (buttonState[i] == HIGH) {
//check if button 1
if(i == 0){
//select next LED
j++;
}
//else button 2
else{
// if the current state of the 2nd button is HIGH
while(i == 1){
//if current value of led is false, put it true
if(values[j] == false){
//put led on
digitalWrite(leds[j], true);
values[j] = true;
delay(50);
}else{
//put led off
digitalWrite(leds[j], false);
delay(50);
values[j] = false;
}
//go back to button 1?
i = 0;
}
}
//go back to button 1?
i = 0;
}
}
// save the current state as the last state,
// for next time through the loop
lastButtonState[i] = buttonState[i];
// wait a little
delay(50);
}
}
}
void fade(){
//put every led on half-on
for(int i = 0; i < sizeof(leds); i++){
analogWrite(leds[i], 100);
}
}

In C and C++, if you want to compare two values to check if they are equal, you have to use == (the comparison operator) instead of = (the assignment operator). You accidentily use the wrong operator here:
while(i = 1){
And here:
if(values[j] = false){
Change those to ==.

Related

I was wondering if someone could help me re-format my code to fix the loop I made

I was wondering what mistake I made in the line that is formatted like this "''" because I was wondering why my code wouldn't move back to the right to bounce back and forth between walls. I put the code that I need help in with single quotations. This is my frist time on stack, so any tips would be appreciated.
PImage invader, invader2, invader3, invader4, invader5, space, tank;
int tankX = 400;
PImage [] picArray = new PImage [7];
int invaderState = 2;
int timer = 0;
int lap = 0;
int [] alienXPos = {100, 180, 260, 340, 420, 500, 580, 660, 740, 820};
//had to add a few zeros on alienYPos otherwise the loop would bug out and wouldn't work
int[] alienYPos = {40, 140, 240, 340, 0, 0, 0, 0, 0, 0};
boolean moveLeft, moveRight;
int paddleSpeed = 3;
int gameState = 1;
String message1 = "Welcome to space invaders!";
String message2 = "Click space to start!";
boolean movingLeft, movingRight;
void setup() {
size(1000, 1000);
invader = loadImage("invader.jpg");
invader.resize(70, 50);
invader2 = loadImage("invader2.png");
invader2.resize(70, 50);
space = loadImage("space.png");
space.resize(1000, 1000);
tank = loadImage("tank.png");
tank.resize(150, 100);
}
void draw() {
background(space);
timer = millis();
if (timer-lap>800) {
lap = timer;
' **for (int m=0; m <10; m++) {
if (movingRight == false) {
alienXPos[m] += 40;
} else {
alienXPos[m] -= 40;
}
if (alienXPos [m] > 900 && movingRight == false) {
movingRight = true;
for (int l=0; l<10; l++) {
alienYPos[l] += 75;
println("movingleft : " + movingLeft);
println("Moving right : " + movingRight);
}
// if(movingLeft == false){
// alienXPos[m] -= 55;
//}
//else{
// alienXPos [m] += 40;
//}
if (movingLeft == false) {
//alienXPos[m] -=55;
} /*else {
alienXPos[m] ;
}*/
if (alienXPos[m] < 100 && movingLeft == true) {
movingLeft = false;
movingRight = true;
/*for (int l=0; l<10; l++) {
alienYPos[l] += 75;
}** '
println("movingLeft : " + movingLeft);
*/
}
}
}
/* if (alienXPos[m] > 0 && movingLeft == true) {
alienXPos[m] -= 55;
}*/
if (invaderState == 1) {
invaderState = 2;
} else {
invaderState = 1;
}
}
if (tankX > width) {
tankX = 0;
}
if (tankX < 0) {
tankX = 1000;
}
if (gameState == 1) {
drawGameState1();
} else if (gameState == 2) {
drawGameState2();
}
}
void drawGameState1() {
background(#222222);
fill(#000000);
textSize(36);
fill(130, 130, 130);
text(message1, 300, 450);
textSize(20);
text(message2, 430, 600);
}
void drawGameState2() {
background(space);
drawSpaceInvader1();
drawTank();
drawTankMovement();
}
void drawSpaceInvader1() {
for (int i=0; i< 10; i++) {
if (invaderState == 1) {
image(invader, alienXPos[i], alienYPos[0]);
image(invader, alienXPos[i], alienYPos[1]);
image(invader, alienXPos[i], alienYPos[2]);
image(invader, alienXPos[i], alienYPos[3]);
} else if (invaderState == 2) {
image(invader2, alienXPos[i], alienYPos[0]);
image(invader2, alienXPos[i], alienYPos[1]);
image(invader2, alienXPos[i], alienYPos[2]);
image(invader2, alienXPos[i], alienYPos[3]);
}
}
}
void drawTank() {
image(tank, tankX, 700);
}
void drawTankMovement() {
if (moveLeft) {
tankX -= 25;
}
if (moveRight) {
tankX += 25;
}
}
void keyPressed() {
if (gameState == 1) {
if (keyCode == 32) {
gameState = 2;
}
}
if (gameState == 2) {
if (keyCode == LEFT) {
moveLeft = true;
}
if (keyCode == RIGHT) {
moveRight = true;
}
}
}
void keyReleased() {
if (keyCode == LEFT) { // Left Key
moveLeft = false;
}
if (keyCode == RIGHT) { // Right Key
moveRight = false;
}
}
A few things:
Next time, please try and provide a minimal, reproducible example, you were almost there, but you forgot to attach the image files that you use to draw your game out. Running this code gave me errors saying I was missing a few files. I took the liberty of importing some nonsense image and reusing that as your missing assets.
Also missing from your answer is a more implicit title. I think you misunderstood the term "reformatting" code, as that generally refers to the formatting of code. To make your answer likely to be found by others with the same problem, please consider changing the title to what your question is actually about: You can't figure out why your code doesn't reverse the movement of your row of space invaders. Next time, please read this guide on how to write a proper question.
Now to answer your question:
I ran your code and noticed that movingLeft was false whilst movingRight was true. Yet your invaders seem to be running towards the left side of the screen. One of your mistakes was probably getting confused by these variables.
In your code you do
if (movingRight == false) {
alienXPos[m] += 40;
} else {
alienXPos[m] -= 40;
}
Which effectively does the opposite of what you want. In coordinates are oriented like this, assuming we have a 800x400 canvas:
So if you want your invaders to move right, you should be adding to the coordinates when the bool is true, not when it's false. Your logic which flips the invaders direction should be sound:
if (alienXPos[m] < 100 && movingLeft == true) {
movingLeft = false;
movingRight = true;
}
But since in your program due to the above logic error movingLeft is never true, this statement will never run.
One suggestion is that in the simple case of space invaders you don't really need to keep track of two seperate moving variables for each direction, after all, invaders either:
Move to the right
or
Move to the left
Thus you could ditch having two variables and just check, for example, movingRight. If that is true, the invaders should be moving to the right, and if it's false, they should be moving to the left.

How to exit or break from 'for loop' on Arduino C Program

I'm not new to the programming world, but for last 2 weeks I'm working with Arduino C++. I have a strange problem. In general, I have a 7-segment display that will act as an up counter when the condition is 01, down counter when the condition is 10, 00 for reset to zero, and 11 for stop (pause in that number).
The problem is, when the up or down counter is still counting and I've change the state, the 7-segment is still counting! Besides that, I've printed the status of state when state is changed, but nothing happens. I think maybe there's mistakes in my code, I need some advice from you guys. Here is my code:
*FYI, I've try to use break, return, also call loop(), but nothing happens
*saklar1 = switch1
*saklar2 = switch2
#include <SevSeg.h>
SevSeg sevseg;
const int saklar1 = 2;
const int saklar2 = 3;
void setup() {
byte sevenSegments = 1;
byte commonPins[] = {};
byte sevenPins[] = {11, 10, 9, 8, 7, 6, 5, 4};
bool resistor = true;
sevseg.begin(COMMON_CATHODE, sevenSegments, commonPins, sevenPins, resistor);
sevseg.setBrightness(90);
pinMode(saklar1, INPUT);
pinMode(saklar2, INPUT);
Serial.begin(9600);
}
void loop() {
checking(digitalRead(saklar1), digitalRead(saklar2));
}
void checking(bool saklar1, bool saklar2){
if (saklar1 == LOW && saklar2 == LOW) {
setSevSeg(0);
} else if (saklar1 == LOW && saklar2 == HIGH) {
for (int i=0; i<=9; i++) {
setSevSeg(i);
if (saklar1 != LOW || saklar2 != HIGH) {
Serial.println("STATE CHANGED"); //THIS LINE IS NOT EXECUTED OR PRINTED
checking(digitalRead(saklar1), digitalRead(saklar2));
}
}
} else if (saklar1 == HIGH && saklar2 == LOW) {
for (int i=9; i>=0; i--) {
setSevSeg(i);
if (saklar1 != HIGH || saklar2 != LOW) {
checking(digitalRead(saklar1), digitalRead(saklar2));
}
}
} else if (saklar1 == HIGH && saklar2 == HIGH) {
delay(100); //Stop
}
}
void setSevSeg(int num) {
sevseg.setNumber(num);
sevseg.refreshDisplay();
delay(500); //1 detik
}
In the following code, the control exits the for loop when the sensor value exceeds the threshold.
Reference: [https://www.arduino.cc/reference/en/language/structure/control-structure/break]
int threshold = 40;
for (int x = 0; x < 255; x++) {
analogWrite(PWMpin, x);
sens = analogRead(sensorPin);
if (sens > threshold) { // bail out on sensor detect
x = 0;
break;
}
delay(50);
}

How to get enemy that is being hit to disappear

I'm currently working on a school project and I'm trying to make a game similar to galaga. My problem is that whenever the bullet hits the enemy, another enemy would disappear. I believe this is because of the fact that I'm using a for loop and the enemies are being deleted in sequential order. Another problem I am having is with the bullets, I do not know why it slows down and eventually disappears as the number of the enemies decreases. Any help is appreciated.
ArrayList<enemy> e = new ArrayList<enemy>();
ArrayList<bullet> b = new ArrayList<bullet>();
boolean shoot = false;
void setup() {
fullScreen();
//enemy
for (int i = 0; i<5; i++) {
e.add(new enemy(50, 50));
}
//bullet
for (int i = 0; i<5; i++) {
b.add(new bullet(mouseX, mouseY));
}
}
void draw() {
background(255);
for (int p = 0; p<e.size(); p++) {
for (int i = 0; i<b.size(); i++) {
bullet a = b.get(i);
enemy o = e.get(p);
if (a.update()) {
b.remove(i);
}
if (o.col()) {
b.remove(i);
e.remove(i);
}
}
}
//enemy
for (int i = 0; i<e.size(); i++) {
enemy a = e.get(i);
a.display();
}
}
void mouseReleased() {
shoot = true;
b.add(new bullet(mouseX, mouseY));
}
class enemy {
int x, y, w, h;
int enemyX = int(random(width));
int enemyY = int(random(200));
public enemy(int tempenemyW, int tempenemyH) {
int tempenemyX = enemyX;
int tempenemyY = enemyY;
this.x = tempenemyX;
this.y = tempenemyY;
this.w = tempenemyW;
this.h = tempenemyH;
}
void display() {
fill(255, 0, 0);
rect(this.x, this.y, this.w, this.h);
}
boolean col() {
for (int i = 0; i<b.size(); i++) {
bullet a = b.get(i);
if (a.x+a.w>this.x && a.x<this.x+this.w && a.y+a.h+a.bulletSpeed>this.y && a.y+a.bulletSpeed<this.y+this.h) {
return true;
}
}
return false;
}
}
class bullet {
int x, y, w, h;
int bulletSpeed = 10;
public bullet(int tempx, int tempy) {
int tempw = 3;
int temph = 20;
this.x = tempx;
this.y = tempy;
this.w = tempw;
this.h = temph;
}
boolean update() {
this.y -= bulletSpeed;
fill(0, 255, 0);
rect(this.x, this.y, this.w, this.h, 100, 100, 100, 100);
if (x<0 || x>width || y<0 || y>height) {
return true;
} else {
return false;
}
}
}
Your removing the enemy that lives at the index of the bullet instead of the enemy at the index of the enemy. To fix this, try changing the line
e.remove(i);
to
e.remove(p);
I also recommend that you give better variable names. The reason that this was confusing for you is because "i" and "p" aren't very descriptive or helpful. It would have been easier to spot the mistake if the middle of the draw function looked like this:
for (int enemyIndex = 0; enemyIndex<e.size(); enemyIndex++) {
for (int bulletIndex = 0; bulletIndex<b.size(); bulletIndex++) {
bullet currentBullet = b.get(bulletIndex);
enemy currentEnemy = e.get(enemyIndex);
if (a.update()) {
b.remove(bulletIndex);
}
if (currentEnemy.col()) {
b.remove(bulletIndex);
e.remove(bulletIndex); // Clearly the wrong index!
}
}
}
Then you could go further by changing the names of your lists to "bullets" and "enemies" instead of just "b" and "e" :p
Teddy's answer is half the story. The other half of the story is that you're removing items from the list as you loop over it.
Let's say you have a loop like this:
for(int index = 0; index < list.size(); index++){
if(list.get(index).contains("remove me")){
list.remove(index);
}
}
And let's say your list looks like this:
0: "keep"
1: "remove me one"
2: "remove me two"
3: "keep"
Go through the loop with this list in mind. When index is 0, it sees "keep" and doesn't do anything. Now index is 1 and it sees "remove me one" so it removes the item at index 1 and every index after that shifts down one, making the list this:
0: "keep"
1: "remove me two"
2: "keep"
But index is still 1 at the end of the loop, so it increases to 2, and the next iteration sees "keep".
In other words, we skip over "remove me two" because we never check that index when it's shifted down by one.
The solution to this problem is to either use an Iterator or to loop backwards over the list.
Shameless self-promotion: I wrote a tutorial on using ArrayLists in Processing available here. See the section on removing items from an ArrayList.

Holding a push button for 3 second in a for loop

I have a button that basically has two functions. The aim is:
First push will blink a LED 15 times.
If someone holds the button longer than 3 seconds while the LED is blinking, it should stop and go back to the initial.
So I checked the Arduino's hold a button page and came up with this code. The problem is that I can not properly stop the blinking. The line Serial.println("DONE!!"); never works.
Where should I check if the button is held or not and should I use interrupt to end the for loop?
Here is my code:
int inPin = 2; // the pin number for input (for me a push button)
int ledPin = 9;
int current; // Current state of the button
// (LOW is pressed b/c I'm using the pullup resistors)
long millis_held; // How long the button was held (milliseconds)
long secs_held; // How long the button was held (seconds)
long prev_secs_held; // How long the button was held in the previous check
byte previous = LOW;
unsigned long firstTime; // how long since the button was first pressed
long millis_held2; // How long the button was held (milliseconds)
long secs_held2; // How long the button was held (seconds)
long prev_secs_held2; // How long the button was held in the previous check
byte previous2 = LOW;
unsigned long firstTime2; // how long since the button was first pressed
void setup() {
Serial.begin(9600); // Use serial for debugging
pinMode(ledPin, OUTPUT);
digitalWrite(inPin, INPUT); // Turn on 20k pullup resistors to simplify switch input
}
void loop() {
current = digitalRead(inPin);
// if the button state changes to pressed, remember the start time
if (current == HIGH && previous == LOW && (millis() - firstTime) > 200) {
firstTime = millis();
}
millis_held = (millis() - firstTime);
secs_held = millis_held / 1000;
// This if statement is a basic debouncing tool, the button must be pushed for at least
// 100 milliseconds in a row for it to be considered as a push.
if (millis_held > 50) {
// check if the button was released since we last checked
if (current == LOW && previous == HIGH) {
// HERE YOU WOULD ADD VARIOUS ACTIONS AND TIMES FOR YOUR OWN CODE
// ===============================================================================
//////////////////////////////////////////////////////// Button pressed Blink 15 times.
if (secs_held <= 0) {
for (int i = 0; i < 15; i++) {
ledblink(1, 750, ledPin);
current = digitalRead(inPin);
if (current == HIGH && previous == LOW && (millis() - firstTime2) > 200) {
firstTime2 = millis();
}
millis_held2 = (millis() - firstTime2);
secs_held2 = millis_held2 / 1000;
if (millis_held2 > 50) {
Serial.print("previousA ");
Serial.print(previous);
Serial.print(" currentA ");
Serial.println(current);
current = digitalRead(inPin);
if (current == HIGH && previous2 == HIGH) {
Serial.println("ALMOST! ");
Serial.println(secs_held2);
if (secs_held2 >= 2 && secs_held2 < 6) {
Serial.println("DONE!!");
}
}
}
previous2 = current;
prev_secs_held2 = secs_held2;
}
}
}
}
previous = current;
prev_secs_held = secs_held;
}
void ledblink(int times, int lengthms, int pinnum) {
for (int x = 0; x < times; x++) {
digitalWrite(pinnum, HIGH);
delay (lengthms);
digitalWrite(pinnum, LOW);
delay(lengthms);
}
}
This is how it would be done without using delay():
int inPin = 2;
int ledPin = 9;
long pressTimer;
long blinkTimer;
long blinkHalfDelay = 500; //milliseconds
int blinkCount = 0;
int blinkLimit = 15;
bool blinkFlag = false;
bool blinkLatch = true;
bool currentBtnState = false;
bool lastBtnState = false;
void setup() {
}
void loop() {
lastBtnState = currentBtnState;
currentBtnState = digitalRead(inPin);
//on rising edge, start timers
if(currentBtnState==true && lastBtnState==false)
{
pressTimer = millis();
}
//debounce activation
if(currentBtnState==true && !blinkFlag && millis()-pressTimer > 50)
{
blinkTimer = millis();
blinkCount = 0;
blinkLatch = true;
blinkFlag = true;
//functional execution would go here
}
if(currentBtnState = false || (millis()-pressTimer>3000 && currentBtnState == true))
{
blinkCount=blinkLimit;
blinkLatch = false;
}
if(blinkFlag == true)
{
if(millis()-blinkTimer > blinkHalfDelay)
{
blinkTimer = millis();
if(blinkLatch)
{
digitalWrite(pinnum, HIGH);
}
else
{
digitalWrite(pinnum, LOW);
blinkCount+=1;
}
}
if(blinkCount>blinkLimit)
{
blinkFlag = false;
digitalWrite(pinnum, LOW);
}
}
}
ps: sorry for not correcting your code directly, but it was kinda hard to read...

Controlling sprite with 2 dimensional array SDL2

I'm currently learning to create my first game ever, and I chose SDL2 to be the game engine. I can make animation for the main character sprite separately. However I figured that it would be ridiculously tedious to control the sprite that way.
So I loaded the sprite sheet into a 2 dimensional array hoping that I would be able to control the sprite with all kind of actions with just that one sprite sheet.
#define HOR_FRAMES 16
#define VER_FRAMES 16
// These are for the images and sprites
Sprite catGif;
SDL_Rect catRect[VER_FRAMES][HOR_FRAMES];
bool load()
{
bool success = true;
// Load cat sprite sheets
if (!catGif.loadFromFile("./assets/pets/fighter_cat_sprite/cat_sprite_base_64.png",
sceneRenderer, 0X00, 0x00, 0x00))
{
printf("%s", SDL_GetError());
success = false;
}
else
{
int initX = 0;
int initY = 0;
for (int ver = 0; ver < VER_FRAMES; ver++)
{
for (int hor = 0; hor < HOR_FRAMES; hor++)
{
catRect[ver][hor].x = initX;
catRect[ver][hor].y = initY;
catRect[ver][hor].w = 64;
catRect[ver][hor].h = 64;
initX += 64;
}
initX = 0;
initY += 64;
}
initX = 0;
initY = 0;
}
return success;
}
Then I created a simple enum to define the actions, which is the rows in the sprite sheet
enum Actions{
IDLE,
WALK,
TOTAL
};
After that, in main(), I add the control logic and set the variables in away that I think appropriately for rendering.
#include "init.h"
#include "Sprite.h"
LTexture background(SCREEN_WIDTH, SCREEN_HEIGHT);
SDL_Rect bgRect;
LTexture foreground(SCREEN_WIDTH, SCREEN_HEIGHT);
SDL_Rect fgRect;
int frame = 0;
int maxFrame = 0;
SDL_RendererFlip flipType;
int main(int argc, char* argv[])
{
init();
load();
int action;
bool quitFlag = false;
SDL_Event event;
while (!quitFlag)
{
action = IDLE;
while (SDL_PollEvent(&event) != 0) // Handle events in queue
{
if (event.type == SDL_QUIT ||
event.key.keysym.sym == SDLK_ESCAPE)
quitFlag = true;
}
const Uint8* states = SDL_GetKeyboardState(NULL);
if (states[SDL_SCANCODE_A])
{
maxFrame = 8;
action = WALK;
flipType = SDL_FLIP_HORIZONTAL;
catGif.moveLeft();
}
else if (states[SDL_SCANCODE_D])
{
maxFrame = 8;
action = WALK;
flipType = SDL_FLIP_NONE;
catGif.moveRight();
}
else
{
maxFrame = 4;
action = IDLE;
}
// Drawing
background.clipRender(0, 0, sceneRenderer, &bgRect);
foreground.clipRender(0, SCREEN_HEIGHT / 2, sceneRenderer, &fgRect);
SDL_Rect* currFrame = &catRect[action][frame / maxFrame];
int x = catGif.xGetter();
int y = catGif.yGetter();
catGif.render(x, y, sceneRenderer, currFrame, NULL, 0, flipType);
// Update
SDL_RenderPresent(sceneRenderer);
frame++;
if (frame / maxFrame == maxFrame)
{
frame = 0;
}
}
clean();
return 0;
}
The sprite played smoothly as I pressed the A/D buttons. However, problems appeared after I released the buttons, the sprite sheet continued to play itself through to the end and then the sprite disappeared, even though the "action" variable has been set and there is no way that it can increment itself, I'm pretty sure about that.
Please help me to understand how that happened, hopefully I can try to fix it, or take another approach. Thank you.
I use code::blocks 16.01 on Fedora linux.
And this is the sprite sheet: cat_sprite_sheet
You must reset frame to 0 when changing the animation state.
{
maxFrame = ...;
frame = 0;
...
}
The bug is there because of == check in your frame increment. If current frame is 40 and you release A/D, maxFrame is set back to 4. frame / maxFrame = 40 / 4 = 10 > 4, so it will never be equal to maxFrame, and frame keeps increasing forever, thus make your sprite to disappear when [frame / maxFrame] goes out of bound. Reset frame to 0 will solve this.

Resources