EDITED: I got the program to complete the loop, now it's just that it gives me a bunch of 0's before it completes the loop - so here's an updated version of my code.
Trying to create a program that first turns LEDs on one after one, and once they're all lit up - turns them off one after one, and keeps turning them on and off. I have succeeded in lighting them up and turning them off, but the program seems to get stuck for a bit when it's turned them all off before it completes the loop and starts over.
int t=1000;
unsigned long time;
int pin;
int value;
int a;
int b;
void setup() {
// put your setup code here, to run once:
for(pin=2; pin<8; pin++){
pinMode(pin, OUTPUT);
}
Serial.begin(9600);
}
void more(){
for(int i=1; i<8; i++){
for(pin=i; pin<8; pin++){
digitalWrite(pin,HIGH);
a=bitRead(PORTD,7);
b=bitRead(PORTD,2);
for(pin=2; pin<8; pin++){
value=bitRead(PORTD,pin);
if(value==1){
Serial.print("1 ");
}
else{
Serial.print("0 ");
}
}
Serial.println();
Serial.println();
delay(t);
}
}
}
void less(){
for(int j=7; j>=2; j--){
for(int p=j; p>1; p--){
digitalWrite(p,LOW);
a=bitRead(PORTD,7);
b=bitRead(PORTD,2);
for(pin=2; pin<8; pin++){
value=bitRead(PORTD,pin);
if(value==1){
Serial.print("1 ");
}
else{
Serial.print("0 ");
}
}
Serial.println();
Serial.println();
delay(t);
}
}
}
void loop() {
// put your main code here, to run repeatedly:
Serial.print("Time: ");
time=millis();
Serial.println(time);
a=bitRead(PORTD,7);
b=bitRead(PORTD,2);
do{
more();
}while(a==0);
do{
less();
}while(b==1);
}
a=0 is always false and b=1 is always true because they do assignment and evaluated as what is assigned.
Use == operator to compare numbers.
Related
I'm using the default code for a PMS5003 particulate matter sensor (with the RTC time features removed for now). However, I don't want to the data output to be on a constant loop; instead, I want to collect data only at certain intervals, for example every 10 seconds or every minute. To do this, I simply added a delay line at the end of the main loop. And with even the slightest delay of 1 second, I quickly run into checksum errors, although the code works fine without the delay.
#include <SoftwareSerial.h>
SoftwareSerial pmsSerial(2, 3);
void setup() {
// our debugging output
Serial.begin(9600);
// sensor baud rate is 9600
pmsSerial.begin(9600);
}
struct pms5003data {
uint16_t framelen;
uint16_t pm10_standard, pm25_standard, pm100_standard;
uint16_t pm10_env, pm25_env, pm100_env;
uint16_t particles_03um, particles_05um, particles_10um, particles_25um, particles_50um, particles_100um;
uint16_t unused;
uint16_t checksum;
};
struct pms5003data data;
void loop() {
if (readPMSdata(&pmsSerial)) {
// reading data was successful!
Serial.println();
Serial.println("Concentration Units (environmental)");
Serial.print("PM 1.0: "); Serial.print(data.pm10_env);
Serial.print("\t\tPM 2.5: "); Serial.print(data.pm25_env);
}
//This line causes issues
delay(1000);
}
boolean readPMSdata(Stream *s) {
if (! s->available()) {
return false;
}
// Read a byte at a time until we get to the special '0x42' start-byte
if (s->peek() != 0x42) {
s->read();
return false;
}
// Now read all 32 bytes
if (s->available() < 32) {
return false;
}
uint8_t buffer[32];
uint16_t sum = 0;
s->readBytes(buffer, 32);
// get checksum ready
for (uint8_t i=0; i<30; i++) {
sum += buffer[i];
}
/* debugging
for (uint8_t i=2; i<32; i++) {
Serial.print("0x"); Serial.print(buffer[i], HEX); Serial.print(", ");
}
Serial.println();
*/
// The data comes in endian'd, this solves it so it works on all platforms
uint16_t buffer_u16[15];
for (uint8_t i=0; i<15; i++) {
buffer_u16[i] = buffer[2 + i*2 + 1];
buffer_u16[i] += (buffer[2 + i*2] << 8);
}
// put it into a nice struct :)
memcpy((void *)&data, (void *)buffer_u16, 30);
if (sum != data.checksum) {
Serial.println("Checksum failure");
return false;
}
// success!
return true;
}
I suspect that the delay is causing the sensor and the Arduino to somehow desync. I also think it could possibly have to do with poor soldering of the sensor wires (though this wouldn't explain why the sensor works perfectly without the delay). Anyone know what's causing this issue, and how I might fix it?
Thanks.
I am new to arduino and am trying to make a for loop in it which just prints "Blink" using Serial.println(); command 3 times, however it isn't working properly and it just prints "Blink" forever and doesn't stop at all. What am I doing wrong in the code below? Would be grateful to any help.
void setup() {
Serial.begin(9600);
}
void loop() {
for(int i=0; i<3; i++){
Serial.println("Blink");
delay(500);
}
}
You put the for-loop inside the loop() function which runs endlessly.
Simply move it to setup():
void setup() {
Serial.begin(9600);
for(int i=0; i<3; i++){
Serial.println("Blink");
delay(500);
}
}
void loop() {
}
The arduino code is not a regular program. you have to keep in mind that the arduino code is an operation system which has to run endlessly Otherwise the arduino will stop. therefore there are 2 functions, the setup() that runs one time and the loop() that runs infinity times.
I am not getting why this is not working. I was researching on fixes and they say to add that "if" block in the void loop. Well, that was always in the void loop. Can you tell me the meaning and fix? Also, if there are more errors, please notify me so I can fix it. My code can be a little disorganized.
My code:
#include <LiquidCrystal.h>
LiquidCrystal lcd (7,8,9,10,11,12);
int pinDHT11 = 2;
SimpleDHT11 dht11;
void setup() {
Serial.begin(9600);
lcd.begin(16,2);
}
void loop() {
}
if (dht11.read(pinDHT11, &temperature, &humidity,data))
Serial.print("Read DHT11 failed");
return;
byte temperature = 0;
byte humidity = 0;
byte data[40] = {0};
if(dht11.read (pinDHT11, &temperature, &humidity, data))
return;
Serial.print("Read DHT11 failed");
Serial.println("=================================");
Serial.println("Sample DHT11...");
// read with raw sample data.
byte temperature = 0;
byte humidity = 0;
byte data[40] = {0};
}
Serial.print("Sample RAW Bits: ");
for (int i = 0; i < 40; i++) {
Serial.print((int)data[i]);
if (i > 0 && ((i + 1) % 4) == 0) {
Serial.print(' ');
}
}
Serial.println("");
Serial.print("Sample OK: ");
Serial.print((int)temperature); Serial.print("*C,");
Serial.print((int)humidity); Serial.println("%");
lcd.setCursor(0,0);
lcd.print((int)temperature);
lcd.setCursor(0,1);
lcd,print((int)humidity);
// DHT11 sampling rate is 1HZ.
delay(1000);
Your void loop is empty.
void loop() {
}
The error message is caused because you may not have code outside of functions. The only thing that is allowed outside functions are declarations.
There is a } without a matching {.
You also have two unconditional return statements.
, instead of .
lcd,print((int)humidity);
currently am working on project to open a door with access code using arduino UNO and a servo motor. Normal operation requires entering access code using keypad which is working fine. Another option requires pressing a button that causes an interrupt to rotate the servo motor. My problem is my interrupt only works once and never works again. Plus how do i put the for-loop to rotate the servo motor inside the interrupt function with a delay. I know that is not possible but am calling another function that has the delayMicroseconds but all this is not working. Below is my implementation please help
#include <Keypad.h>
#include <LiquidCrystal.h>
#include <Servo.h>
Servo servo;
const int openButtonPin = 2;
void setup() {
// put your setup code here, to run once:
servo.attach(5);
pinMode(openButtonPin, INPUT); //Pin 2 is input
attachInterrupt(0, enforceOpenAccess, HIGH); // PIN 2
}
void(* resetFunc)(void) = 0;
void loop()
{
//My other keypad implementations go here
}
void myDelay(int x) // function to cause delay in the interrupt
{
for(int i = 0; i<x; i++)
{
delayMicroseconds(1000);
}
}
void enforceOpenAccess() // ISR
{
for(int k =0; k<=180; k+=2)
{
servo.write(k); //rotate the servo
myDelay(30); //delay the rotation of the servo
}
}
The code above is run on arduino UNO being simulated in proteus and the interrupt button is a push button. Please if there is other ways of implementing that but with the same behaviour as I have described above help out. Thanks a lot
There are a couple of problems in the slice of code you posted. Just for completeness, you should post the loop function, since we can't guess what you wrote inside.
Just one comment: did you put a pullup? Otherwise use INPUT_PULLUP instead of INPUT for the button pinmode.
The main one is that you attached the interrupt for the HIGH mode, which will trigger the interrupt any time the pin is up, not on the rising edge. And please use the macro digitalPinToInterrupt to map to the correct pin:
attachInterrupt(digitalPinToInterrupt(openButtonPin), enforceOpenAccess, RISING);
Then.. Let's improve the code. You really should use the interrupts only when strictly necessary when you have to respond IMMEDIATELY (= less than a couple of milliseconds) to an input. Here you don't have to, so it's MUCH better to check for the button in the loop (more on turning the motor following)
uint8_t lastState;
void setup()
{
...
lastState = LOW;
}
void loop()
{
uint8_t currentState = digitalRead(openButtonPin);
if ((currentState != lastState) && (currentState == HIGH))
{
// Start turning the motor
}
lastState = currentState;
...
}
This will enable you to properly debounce the button too:
#include <Bounce2.h>
Bounce debouncer = Bounce();
void setup()
{
...
pinMode(openButtonPin, INPUT); //Pin 2 is input
debouncer.attach(openButtonPin);
debouncer.interval(5); // interval in ms
}
void loop()
{
debouncer.update();
if (debouncer.rose())
{
// Start turning the motor
}
...
}
If, on the other way, you REALLY want to use the interrupts (because waiting for a couple of milliseconds is too much for you), you should do something like this:
#include <Bounce2.h>
Bounce debouncer = Bounce();
void setup()
{
...
pinMode(openButtonPin, INPUT);
attachInterrupt(digitalPinToInterrupt(openButtonPin), enforceOpenAccess, RISING);
}
void loop()
{
...
}
void enforceOpenAccess() // ISR
{
// Start turning the motor
}
It looks like your code? No, because now we'll speak about turning the motor
You should NOT use delays to make steps, because otherwise you will wait for 30ms * 180 steps = 5.4s before being able to do anything else.
You can, however, make a sort of reduced state machine. You want your servo to move from 0 to 180 in steps of 1. So let's code the "don't move" state with any value greater than 180, and consequently we can do something like this in the loop:
unsigned long lastServoTime;
uint8_t servoPosition = 255;
const int timeBetweenSteps_in_ms = 30;
void loop()
{
...
if (servoPosition <= 180)
{ // servo should move
if ((millis() - lastServoTime) >= timeBetweenSteps_in_ms)
{
lastServoTime += timeBetweenSteps_in_ms;
servoPosition++;
if (servoPosition <= 180)
servo.write(servoPosition);
}
}
}
Then, using any of the previous examples, instead of // Start turning the motor write
lastServoTime = millis();
servoPosition = 0;
servo.write(servoPosition);
This way you won't block the main loop even when the button is pressed
This is what is in my loop()
char key = keypad.getKey();
if(key)
{
if(j < 10)
{
studentNumber[j] = key;
//holdMaskedNumber[j] = '*';
lcd.setCursor(0,2);
lcd.print(String(studentNumber));
if(j == 9)
{
studentNumber[9] = '\0';
//holdMaskedNumber[9] = 0;
lcd.clear();
//String number = String(studentNumber);
//lcd.print(number);
//delay(1000);
//lcd.clear();
lcd.print("Access Code");
}
j++;
}
else
{
if(i < 5)
{
accessCode[i] = key;
holdMaskedCode[i] = '*';
lcd.setCursor(1,2);
lcd.print(String(holdMaskedCode));
if(i == 4)
{
holdMaskedCode[5] = '\0';
accessCode[5] = '\0';
//lcd.clear();
//lcd.setCursor(0,0);
//accessCodeString = String(accessCode);
//lcd.print(accessCodeString);
//delay(1000);
lcd.clear();
for(int i =0; i<6; i++)
{
lcd.print("Please wait.");
delay(500);
lcd.clear();
lcd.print("Please wait..");
delay(500);
lcd.clear();
lcd.print("Please wait...");
delay(500);
lcd.clear();
}
digitalWrite(4, HIGH);
lcd.print("Access Granted");
for(int k =0; k<=180; k+=2)
{
servo.write(k);
delay(30);
}
resetFunc();
}
i++;
}
}
}
I am trying to implement three different functions for one button in an Arduino project. Click, double click and hold.
I have to use interrupts and let the system sleep as much as possible, because the final product will have to run on a coin cell for a few months.
#include <Ports.h>
#include <RF12.h>
#include <avr/sleep.h>
#include <PinChangeInt.h>
#include <VirtualWire.h>
ISR(WDT_vect) { Sleepy::watchdogEvent(); }
char *controller;
const int buttonPin = 3;
bool stateSingle = false;
bool stateDouble = false;
bool stateLong = false;
void setup() {
pinMode(13, OUTPUT);
pinMode(6, OUTPUT);
pinMode(7, OUTPUT);
pinMode(5, OUTPUT);
// vw_set_ptt_inverted(true);
// vw_set_tx_pin(12);
// vw_setup(4000);
//
Serial.begin(9600);
PCintPort::attachInterrupt(buttonPin, wakeUp, HIGH);
}
void wakeUp() {
}
void loop() {
cli();
int i = 0;
while (digitalRead(buttonPin) == HIGH) { // Wait until button is LOW, or has been high for more than 600ms
Sleepy::loseSomeTime(50);
if (i > 12)
break;
i++;
}
if (digitalRead(buttonPin) == HIGH)
longTapAction();
else {
i = 0;
while (digitalRead(buttonPin) == LOW) { // Wait for possible double press
Sleepy::loseSomeTime(50);
if (i > 8)
break;
i++;
}
if (digitalRead(buttonPin) == HIGH) {
doubleTapAction();
while (digitalRead(buttonPin) == HIGH)
Sleepy::loseSomeTime(50);
} else
singleTapAction();
}
}
void singleTapAction() {
stateSingle = !stateSingle;
digitalWrite(5, stateSingle ? HIGH : LOW);
sei();
Sleepy::powerDown();
}
void doubleTapAction() {
stateDouble = !stateDouble;
digitalWrite(6, stateDouble ? HIGH : LOW);
sei();
Sleepy::powerDown();
}
void longTapAction() {
stateLong = !stateLong;
digitalWrite(7, stateLong ? HIGH : LOW);
sei();
Sleepy::powerDown();
}
The problem is that this is not always correctly working.
Because I'm using interrupts, millis() inside void loop() is not reliable, for some reason.
For any double click, and for any hold action, the single click function also gets called. I suspect this is due to multiple interrupts firing, but I have no way to test this. Also, sometimes, the double click seems to need only one click. Is my thinking wrong, did I forget something?
If you are seeing singleTapAction and doubleTapAction triggering too often, the problem could be that your method doesn't really debounce the button inputs, meaning you may read spurious noise on any click as a single press or double press. E.G your first while loop will exit almost immediately if there is a noisy input, which makes the following behavior difficult to predict.
https://www.arduino.cc/en/Tutorial/Debounce
If you have a look at the linked example on the arduino site - a possible solution is to record the period of time an input has been present and ignore any inputs of less than a certain period. Modifying your code to do this could stop the spurious calls.