Atmel Studio + Arduino + Library : function "not declared in this scope" - c++
First of all, I copied/paste th code to see if it compliles in Arduino IDE, and it does, so I guess it's not a C++ related issue but maybe something more Atmel Studio or linker related.
I recently decided to switch from Arduino IDE to Atmel Studio to develop and program Arduino boards.
I have this project where I use a .h/.c library that I wrote, which is located in "../Lib". I have added the library with "Add existing item" and "Add as Link", because I wanted to work with the original code not a copy (a few things still need to be added to it)
A first it builded without any problem, but then I added an extra function in the library called "determineWinningPosition()". Now compilation returns an error :
D:\Google Drive\ISIB\5 - Mecatronic\Controller_v5_AS\Controller_v5_AS\Controller_v5\Sketch.cpp(76,28): error: 'determineWinningPositions' was not declared in this scope
determineWinningPositions();
The function prototype is declared in the library header "LetMeOut.h" :
#include <Arduino.h>
#include <Wire.h>
#include <avr/sleep.h>
#include <avr/power.h>
#include <EEPROM.h>
#include <stdlib.h>
// Key words
#define MOTOR1 (0)
#define MOTOR2 (1)
#define MAX_SPEED (15)
#define SIZE_RAND_SEQ (100)
#define BUTTON_TIMEOUT (10) // -> 1s
#define WINNING_POS_TOLERANCE (3)
#define GLOBAL_STATE_SIZE (7)
#define STATE0 (3)
#define STATE1 (2)
#define STATE2 (0)
#define STATE3 (1)
#define START (5)
#define STOP (10)
#define CHANGE_SPEED (15)
#define INIT_POS (20)
#define START_SPEED (25)
#define RESET_CMD (30)
#define GO_TO_POS (35)
#define UNLOCK_DOOR (40)
#define LOCK_DOOR (45)
#define CHANGE_WINNING_POS (50)
#define TRUE (1)
#define FALSE (0)
#define EEPROM_1 (0)
#define EEPROM_2 (1)
// Pins
#define DIR_M1 (A0)
#define DIR_M2 (A1)
#define EN_M1 (A2)
#define EN_M2 (A3)
#define SCL_PIN (A4)
#define SDA_PIN (A5)
#define STARTED_PIN (2)
#define A1_PIN (3)
#define B1_PIN (4)
#define A2_PIN (5)
#define CTL_M1 (6)
#define B2_PIN (7)
#define START_PIN (8)
#define STOP_M2 (9)
#define SUCCEED_PIN (10)
#define CTL_M2 (11)
#define STOP_M1 (12)
#define DOOR_PIN (13) // LED
// Prototypes
void Timer1_ISR(void);
void receiveEvent(int howMany);
void requestEvent();
void initI2C(void);
void initMotors(void);
void initEncoder(void);
void initDirectionTimer(void);
void setMotorSpeed(uint8_t motor, uint8_t motorSpeed, uint8_t dir);
void setAllMotorSpeed(uint8_t motorSpeed);
void stopMotor(uint8_t motorID);
void stopAllMotors (void);
void startMotor(uint8_t motorID);
void startAllMotors (void);
void buttonManager(void);
void directionManager(void);
void i2cCommandManager(void);
void printPosition(bool b);
void goToPosition(uint8_t position1_, uint8_t position2_);
void readEncoder(void);
void determineWinningPositions(void);
The function is implemented in "LetMeOut.cpp" :
#include "LetMeOut.h"
extern uint8_t directionChangeCounter1, directionChangeCounter2;
extern uint8_t directionChangeCounterTopValue1;
extern uint8_t directionChangeCounterTopValue2;
extern bool direction1;
extern bool direction2;
extern bool counterChanged;
extern uint8_t button1Counter;
extern bool button1CounterStarted;
extern uint8_t button2Counter;
extern bool button2CounterStarted;
extern volatile uint8_t startButtonCounter;
extern volatile bool startButtonCounterStarted;
extern uint8_t cmd[3];
extern uint8_t globalState[GLOBAL_STATE_SIZE];
extern bool newCmd;
const uint8_t randomSeq[SIZE_RAND_SEQ] = {9, 15, 8, 10, 10, 10, 17, 12, 6, 16, 6, 8, 14, 15, 19, 15, 9, 20, 13, 17, 7, 15, 13, 15, 5, 7, 10, 6, 8, 9, 14, 9, 19, 11, 15, 17, 17, 7, 18, 12, 8, 20, 12, 11, 6, 16, 19, 17, 16, 10, 14, 14, 18, 13, 5, 20, 17, 10, 17, 12, 15, 12, 16, 12, 12, 18, 18, 19, 13, 16, 6, 7, 16, 17, 12, 11, 19, 12, 19, 13, 15, 18, 5, 7, 8, 8, 16, 16, 8, 14, 17, 17, 13, 6, 6, 8, 7, 10, 20, 13};
extern uint8_t index1;
extern uint8_t index2;
extern uint8_t speedSetting;
extern volatile bool started;
extern bool initDone;
extern bool doorUnlocked;
extern volatile bool currentA1, currentB1, currentA2, currentB2;
extern volatile int currentState1, previousState1, currentState2, previousState2, position1, position2;
extern volatile bool printPos;
extern uint8_t winningPosition1;
extern uint8_t winningPosition2;
extern volatile bool succeed;
extern volatile bool motor1Started;
extern volatile bool motor2Started;
extern int* winningPositionList1;
extern int* winningPositionList2;
/************************************************************************************************/
/********************************** Interrupts and Callbacks ************************************/
/************************************************************************************************/
// Interrupt service routine called at every timer 1 overflow : every 100 ms
// Used to measure time between every speed changes and to implement a timeout every 1s to prevent
// the user from "machine gunning" the buttons
void Timer1_ISR(void)
{
// Increase both counters used for speed changes and notify the loop() there's been a change
directionChangeCounter1++;
directionChangeCounter2++;
counterChanged = 1;
// Prevent the user from "machine gunning" the buttons
if (button1CounterStarted)
{
button1Counter++;
if (button1Counter >= BUTTON_TIMEOUT)
{
button1CounterStarted = 0;
button1Counter = 0;
}
}
if (button2CounterStarted)
{
button2Counter++;
if (button2Counter >= BUTTON_TIMEOUT)
{
button2CounterStarted = 0;
button2Counter = 0;
}
}
// Debounce START_PIN
if (startButtonCounterStarted)
{
startButtonCounter++;
if (startButtonCounter >= 2)
{
startButtonCounterStarted = 0;
startButtonCounter = 0;
}
}
}
// Callback function that defines the behaviour in case of some received I2C bytes
void receiveEvent(int howMany)
{
// Read the incoming bytes
cmd[0] = Wire.read();
if (Wire.available())
cmd[1] = Wire.read();
if (Wire.available())
cmd[2] = Wire.read();
// Get rid of any other unread message
while (Wire.available() != 0)
{
Wire.read();
}
// Notify the loop() that there's a new command to be handled
newCmd = 1;
}
// Callback function that defines the behaviour in case of a received request
// for a global state update -> send the global state to the Rapsberry Pi
void requestEvent()
{
// Prepare the message to be sent
globalState[0] = started;
globalState[1] = succeed;
globalState[2] = speedSetting;
globalState[3] = doorUnlocked;
globalState[4] = initDone;
globalState[5] = winningPosition1;
globalState[6] = winningPosition2;
// Send the global state to the raspberry pi
for (int i=0; i<GLOBAL_STATE_SIZE; i++)
{
Wire.write(globalState[i]);
}
}
/************************************************************************************************/
/********************************** Initializations *********************************************/
/************************************************************************************************/
// Initialize the I2C
void initI2C(void)
{
Wire.begin(0x18);
Wire.onReceive(receiveEvent);
Wire.onRequest(requestEvent);
// Disable internal pullup
digitalWrite(SCL_PIN, LOW);
digitalWrite(SDA_PIN, LOW);
}
// Motor control related intializations
void initMotors(void)
{
// Initialize timer 0 to generate a square wave on OC0A (CTL_M1 - D6)
// Toggle OC0A on compare match (non-PWM mode), WF gen CTC mode
TCCR0A = _BV(COM0A0) | _BV(WGM21);
// Prescale = 1024 => period = 2 * 64us * (OCR0A+1);
TCCR0B = _BV(CS02) | _BV(CS00);
// Set initial value of compare (sets the frequency)
OCR0A = MAX_SPEED;
// => Changing OCR0A value will set frequency of the square wave and thus the motors speed
// Initialize timer 2 to generate a square wave on OC2A (CTL_M2 - D11)
// Toggle OC2B on compare match (non-PWM mode), WF gen CTC mode
TCCR2A = _BV(COM2A0) | _BV(WGM21);
// Prescale = 1024 => period = 2 * 64us * (OCR2A+1);
TCCR2B = _BV(CS22) | _BV(CS21) | _BV(CS20);
// Set initial value of compare (sets the frequency)
OCR2A = MAX_SPEED;
// => Changing OCR0A value will set frequency of the square wave and thus the motors speed
// Set the correct modes and initialize all the pins that are necessary for motor control
pinMode(CTL_M1, OUTPUT);
pinMode(CTL_M2, OUTPUT);
pinMode(DIR_M1, OUTPUT);
pinMode(DIR_M2, OUTPUT);
pinMode(EN_M1, OUTPUT);
digitalWrite(EN_M1, LOW);
pinMode(EN_M2, OUTPUT);
digitalWrite(EN_M2, LOW);
}
// Initialize pins and interrupts for the encoder
void initEncoder(void)
{
// Configure pin change interrupts (PCINT) on A1, B1, A2 and B2
// -> PCIE2 group
PCICR = _BV(PCIE2);
// Configure PCIE2 interrupt mask
PCMSK2 = _BV(PCINT19) | _BV(PCINT20) | _BV(PCINT21) | _BV(PCINT23);
pinMode(A1_PIN, INPUT);
pinMode(B1_PIN, INPUT);
pinMode(A2_PIN, INPUT);
pinMode(B2_PIN, INPUT);
}
// Initialize timer1 to overflow every 100 ms (used for timing related things)
void initDirectionTimer(void)
{
// Timer 1 config : normal mode
TCCR1A = 0;
// Prescaler 64 ; CTC mode
TCCR1B = _BV(CS11) | _BV(CS10) | _BV(WGM12);
TIMSK1 = 0b00000010;
// Initiate Timer 1 and compare A value
TCNT1 = 0;
OCR1A = 25000; // overflow every 100ms
}
/************************************************************************************************/
/****************************** Motor-related functions *****************************************/
/************************************************************************************************/
// Set the speed of a particular motor
void setMotorSpeed(uint8_t motor, uint8_t motorSpeed, uint8_t dir)
{
// Make sure the speed isn't too fast
if (motorSpeed < MAX_SPEED)
motorSpeed = MAX_SPEED;
// Set the speed by setting OCRxA and the direction by setting DIR_Mx pin
if (motor == MOTOR1)
{
OCR0A = motorSpeed;
digitalWrite(DIR_M1, dir);
}
else if (motor == MOTOR2)
{
OCR2A = motorSpeed;
digitalWrite(DIR_M2, dir);
}
}
// Set the speed of both motors at the same time
void setAllMotorSpeed(uint8_t motorSpeed)
{
// Make sure the speed isn't too fast
if (motorSpeed < MAX_SPEED)
motorSpeed = MAX_SPEED;
OCR0A = motorSpeed;
OCR2A = motorSpeed;
}
// Stop a particular motor by setting its "Not_EN" pin
void stopMotor(uint8_t motorID)
{
if (motorID == MOTOR1)
{
digitalWrite(EN_M1, HIGH);
}
else
{
digitalWrite(EN_M2, HIGH);
}
}
// Stop all motors by setting their "Not_EN" pin
void stopAllMotors (void)
{
digitalWrite(EN_M1, HIGH);
digitalWrite(EN_M2, HIGH);
}
// Start a particular motor by clearing its "Not_EN" pin
void startMotor(uint8_t motorID)
{
if (motorID == MOTOR1)
{
digitalWrite(EN_M1, LOW);
}
else
{
digitalWrite(EN_M2, LOW);
}
}
// Start all motors by clearing their "Not_EN" pin
void startAllMotors (void)
{
digitalWrite(EN_M1, LOW);
digitalWrite(EN_M2, LOW);
}
/************************************************************************************************/
/********************************** Other functions *********************************************/
/************************************************************************************************/
// Check is the player has pushed the button to stop the needles
// and implement corresponding behavior
void buttonManager(void)
{
// Has player pushed button 1 ?
if (!digitalRead(STOP_M1))
{
// If we're not in a button timeout period, stop the motors
if (!button1CounterStarted)
{
stopMotor(MOTOR1);
motor1Started = 0;
button1CounterStarted = 1;
}
}
else
{
if (!button1CounterStarted)
{
startMotor(MOTOR1);
motor1Started = 1;
}
// Keep the motor stopped during the timeout period
else
{
stopMotor(MOTOR1);
motor1Started = 0;
}
}
// Has player pushed button 2 ?
if (!digitalRead(STOP_M2))
{
// If we're not in a button timeout period, stop the motors
if (!button2CounterStarted)
{
stopMotor(MOTOR2);
motor2Started = 0;
button2CounterStarted = 1;
}
}
else
{
if (!button2CounterStarted)
{
startMotor(MOTOR2);
motor2Started = 1;
}
// Keep the motor stopped during the timeout period
else
{
stopMotor(MOTOR2);
motor2Started = 0;
}
}
if (!digitalRead(STOP_M1) && !digitalRead(STOP_M2))
{
bool won1 = 0, won2 = 0;
// Check if needle 1 is in a winning position
for (int i=0; i<2*WINNING_POS_TOLERANCE+1; i++)
{
if (position1 == winningPositionList1[i])
{
won1 = 1;
break;
}
}
// Check if needle 2 is in a winning position
for (int i=0; i < 2*WINNING_POS_TOLERANCE+1; i++)
{
if (position2 == winningPositionList2[i])
{
won2 = 1;
break;
}
}
// If both are winnin, the player won
if (won1 && won2)
{
digitalWrite(DOOR_PIN, HIGH);
doorUnlocked = TRUE;
Serial.println("WINNER");
succeed = 1;
started = 0;
digitalWrite(STARTED_PIN, started);
digitalWrite(SUCCEED_PIN, succeed);
// Make sure all motors are stopped (in case the switches has been pushed between the previous "if" and this one
// (happened once...)
stopAllMotors();
}
}
}
// Manages the direction changes
// This function is called whenever on of the direction change counter value has changed
void directionManager(void)
{
uint8_t newSpeed;
// Check if our counter has overflowed
if (directionChangeCounter1 >= directionChangeCounterTopValue1)
{
// Switch the direction
direction1 = !direction1;
// Reset the counter
directionChangeCounter1 = 0;
// Find the next value in the randomSeq array -> time intervals are random
index1 = (index1+1)%SIZE_RAND_SEQ;
directionChangeCounterTopValue1 = randomSeq[index1];
// Modify the speed according to the time value
// long time value <=> faster speed
// short time value <=> slower speed
if (directionChangeCounterTopValue1 < 10)
newSpeed = speedSetting + 4;
else if (directionChangeCounterTopValue1 < 15)
newSpeed = speedSetting + 2;
else
newSpeed = speedSetting;
setMotorSpeed(MOTOR1, newSpeed, direction1);
}
// Same as for motor 1...
if (directionChangeCounter2 >= directionChangeCounterTopValue2)
{
direction2 = !direction2;
directionChangeCounter2 = 0;
index2 = (index2+1)%SIZE_RAND_SEQ;
directionChangeCounterTopValue2 = randomSeq[index2];
if (directionChangeCounterTopValue2 < 10)
newSpeed = speedSetting + 4;
else if (directionChangeCounterTopValue2 < 15)
newSpeed = speedSetting + 2;
else
newSpeed = speedSetting;
setMotorSpeed(MOTOR2, newSpeed, direction2);
}
}
// Defines how the uC reacts to i2c commands from raspberry pi server
void i2cCommandManager(void)
{
// Did we get any command from the server ?
if (newCmd)
{
// Serial.print("i2c = ");
// Serial.print(cmd[0]);
// Serial.print(" ");
// Serial.print(cmd[1]);
// Serial.print(" ");
// Serial.println(cmd[2]);
switch (cmd[0])
{
case CHANGE_SPEED : // Change the speed
speedSetting = cmd[1];
setAllMotorSpeed(speedSetting);
Serial.print("speed = ");
Serial.println(speedSetting);
break;
case START : // Start and reset the game (unused, replaced by START_SPEED)
startAllMotors();
started = 1;
succeed = 0;
digitalWrite(STARTED_PIN, started);
digitalWrite(SUCCEED_PIN, succeed);
motor1Started = 1;
motor2Started = 1;
digitalWrite(DOOR_PIN, LOW);
doorUnlocked = FALSE;
Serial.println("START");
break;
case STOP : // Stop the game
stopAllMotors();
started = 0;
digitalWrite(STARTED_PIN, started);
motor1Started = 0;
motor2Started = 0;
Serial.println("STOP");
break;
case INIT_POS : // Calibrate the encoder according to the needles positions the user typed on the html form
position1 = cmd[1];
position2 = cmd[2];
initDone = TRUE;
Serial.print("Init Pos = ");
Serial.print(position1);
Serial.print(" ");
Serial.println(position2);
break;
case START_SPEED : // Reset, start and set the speed
startAllMotors();
started = 1;
succeed = 0;
digitalWrite(STARTED_PIN, started);
digitalWrite(SUCCEED_PIN, succeed);
motor1Started = 1;
motor2Started = 1;
digitalWrite(DOOR_PIN, LOW);
doorUnlocked = FALSE;
Serial.print("START SPEED = ");
speedSetting = cmd[1];
setAllMotorSpeed(speedSetting);
Serial.print("speed = ");
Serial.println(speedSetting);
break;
case RESET_CMD : // Reset the game without starting it
stopAllMotors();
succeed = 0;
started = 0;
digitalWrite(STARTED_PIN, started);
digitalWrite(SUCCEED_PIN, succeed);
motor1Started = 0;
motor2Started = 0;
digitalWrite(DOOR_PIN, LOW);
doorUnlocked = FALSE;
Serial.println("RESET");
break;
case GO_TO_POS : // Make the needles go to a certain position
Serial.print("Go to pos ");
Serial.print(cmd[1]);
Serial.print(" ");
Serial.println(cmd[2]);
goToPosition(cmd[1], cmd[2]);
break;
case UNLOCK_DOOR : // Unlock the door
digitalWrite(DOOR_PIN, HIGH);
doorUnlocked = TRUE;
Serial.println("Unlock the door");
break;
case LOCK_DOOR : // Lock the door
digitalWrite(DOOR_PIN, LOW);
doorUnlocked = FALSE;
Serial.println("Lock the door");
break;
case CHANGE_WINNING_POS : // Redefine the winning position, which is written on the EEPROM to keep it when the uC has been stopped
winningPosition1 = cmd[1];
winningPosition2 = cmd[2];
EEPROM.write(EEPROM_1, winningPosition1);
EEPROM.write(EEPROM_2, winningPosition2);
determineWinningPositions();
Serial.print("Change win. pos. to (");
Serial.print(cmd[1]);
Serial.print(",");
Serial.print(cmd[2]);
Serial.println(")");
break;
}
newCmd = 0;
}
}
// Print the current needles position for debug purposes
void printPosition(bool b)
{
if (printPos && b)
{
Serial.print(position1);
Serial.print(" ");
Serial.println(position2);
printPos = 0;
}
}
// Make the needles go to the position the user submitted on the html form
void goToPosition(uint8_t position1_, uint8_t position2_)
{
// Set the speed pretty slow and make sure the motors are started
setAllMotorSpeed(45);
startAllMotors();
bool okPos1 = 0, okPos2 = 0;
// turn the needles clockwise until the both reach the desired position
while(!(okPos1 && okPos2))
{
if (position1 == position1_)
{
stopMotor(MOTOR1);
okPos1 = 1;
}
if (position2 == position2_)
{
stopMotor(MOTOR2);
okPos2 = 1;
}
}
setAllMotorSpeed(speedSetting);
}
// Determine the new motor position when there's been a change on the encoder pins
void readEncoder(void)
{
// The binary combinations of A1 and B1 is always, in decimal :
// 3 2 0 1 3 2 0 1 3 2 0 1 ... when the motor is rotating clockwise
// 1 0 2 3 1 0 2 3 1 0 2 3 ... when the motor is rotating anticlockwise
// Knowing this we can deduce from A1-B1 combinations which way the motor is turning
currentA1 = digitalRead(A1_PIN);
currentB1 = digitalRead(B1_PIN);
// Serial.print(currentA1);
// Serial.print(currentB1);
// Serial.print(" ");
currentState1 = ((char)currentA1<<1) + currentB1;
if (currentState1 != previousState1)
{
if (currentState1 == STATE0)
{
if (previousState1 == STATE3)
{
position1++;
if (position1 == 60)
position1 = 0;
}
else if (previousState1 == STATE1)
{
position1--;
if (position1 == -1)
position1 = 59;
}
}
if (currentState1 == STATE1)
{
if (previousState1 == STATE0)
{
position1++;
if (position1 == 60)
position1 = 0;
}
else if (previousState1 == STATE2)
{
position1--;
if (position1 == -1)
position1 = 59;
}
}
if (currentState1 == STATE2)
{
if (previousState1 == STATE1)
{
position1++;
if (position1 == 60)
position1 = 0;
}
else if (previousState1 == STATE3)
{
position1--;
if (position1 == -1)
position1 = 59;
}
}
if (currentState1 == STATE3)
{
if (previousState1 == STATE2)
{
position1++;
if (position1 == 60)
position1 = 0;
}
else if (previousState1 == STATE0)
{
position1--;
if (position1 == -1)
position1 = 59;
}
}
previousState1 = currentState1;
printPos = 1;
}
currentA2 = digitalRead(A2_PIN);
currentB2 = digitalRead(B2_PIN);
// Serial.print(currentA2);
// Serial.println(currentB2);
currentState2 = ((char)currentA2<<1) + currentB2;
if (currentState2 != previousState2)
{
if (currentState2 == STATE0)
{
if (previousState2 == STATE3)
{
position2++;
if (position2 == 60)
position2 = 0;
}
else if (previousState2 == STATE1)
{
position2--;
if (position2 == -1)
position2 = 59;
}
}
if (currentState2 == STATE1)
{
if (previousState2 == STATE0)
{
position2++;
if (position2 == 60)
position2 = 0;
}
else if (previousState2 == STATE2)
{
position2--;
if (position2 == -1)
position2 = 59;
}
}
if (currentState2 == STATE2)
{
if (previousState2 == STATE1)
{
position2++;
if (position2 == 60)
position2 = 0;
}
else if (previousState2 == STATE3)
{
position2--;
if (position2 == -1)
position2 = 59;
}
}
if (currentState2 == STATE3)
{
if (previousState2 == STATE2)
{
position2++;
if (position2 == 60)
position2 = 0;
}
else if (previousState2 == STATE0)
{
position2--;
if (position2 == -1)
position2 = 59;
}
}
previousState2 = currentState2;
printPos = 1;
}
}
void determineWinningPositions(void)
{
int firstPos = winningPosition1-WINNING_POS_TOLERANCE;
if (firstPos < 0)
firstPos =+ 60;
for (int i=0; i<(2*WINNING_POS_TOLERANCE+1); i++)
{
winningPositionList1[i] = (firstPos+i)%60;
}
firstPos = winningPosition2-WINNING_POS_TOLERANCE;
if (firstPos < 0)
firstPos =+ 60;
for (int i=0; i<(2*WINNING_POS_TOLERANCE+1); i++)
{
winningPositionList2[i] = (firstPos+i)%60;
}
}
The header is included at the beginning of "Sketch.cpp" :
#include <Arduino.h>
#include "LetMeOut.h"
ISR(TIMER1_COMPA_vect );
ISR(PCINT2_vect );
bool debug = 0;
uint8_t directionChangeCounter1 = 0, directionChangeCounter2 = 0;
uint8_t directionChangeCounterTopValue1 = 10;
uint8_t directionChangeCounterTopValue2 = 10;
bool direction1 = 0;
bool direction2 = 0;
bool counterChanged = 0;
uint8_t button1Counter = 0;
bool button1CounterStarted = FALSE;
uint8_t button2Counter = 0;
bool button2CounterStarted = FALSE;
volatile uint8_t startButtonCounter = 0;
volatile bool startButtonCounterStarted = FALSE;
uint8_t cmd[3] = {0,0,0};
uint8_t globalState[GLOBAL_STATE_SIZE];
bool newCmd = 0;
uint8_t index1 = 0;
uint8_t index2 = 64;
uint8_t speedSetting = MAX_SPEED;
volatile bool started = 0;
bool initDone = FALSE;
bool doorUnlocked = FALSE;
volatile bool currentA1, currentB1, currentA2, currentB2;
volatile int currentState1, previousState1, currentState2, previousState2, position1, position2;
volatile bool printPos = 0;
uint8_t winningPosition1;
uint8_t winningPosition2;
volatile bool succeed = 0; // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
volatile bool motor1Started = 0;
volatile bool motor2Started = 0;
int* winningPositionList1;
int* winningPositionList2;
void setup()
{
Serial.begin(2000000);
Serial.println("****************************************************************");
Serial.println("******************** L'horloge déjantée ************************");
Serial.println("************* Eric Bohnes - ISIB 2017-2018**********************");
Serial.println("****************** Master 2 Electronique ***********************");
Serial.println("****************** Cours de Mécatronique ***********************");
Serial.println("*****Collaboration avec l'Escape Game LET ME OUT Bruxelles *****");
Serial.println("****************************************************************\n\n");
initMotors();
initDirectionTimer();
initI2C();
initEncoder();
// Set the player's STOP buttons on INPUT_PULLUP
pinMode(STOP_M1, INPUT_PULLUP);
pinMode(STOP_M2, INPUT_PULLUP);
pinMode(SUCCEED_PIN, OUTPUT);
pinMode(STARTED_PIN, OUTPUT);
// Enable global interrupts
interrupts();
pinMode(START_PIN, INPUT_PULLUP);
stopAllMotors();
winningPosition1 = EEPROM.read(EEPROM_1);
winningPosition2 = EEPROM.read(EEPROM_2);
digitalWrite(STARTED_PIN, started);
digitalWrite(SUCCEED_PIN, succeed);
winningPositionList1 = (int*)malloc((2*WINNING_POS_TOLERANCE+1)*sizeof(int));
winningPositionList2 = (int*)malloc((2*WINNING_POS_TOLERANCE+1)*sizeof(int));
determineWinningPositions();
}
void loop()
{
// If the player didn't succeed yet, check we must change a direction or if the player pushed a button
if (!succeed)
{
// Check if it's time to change direction
if (counterChanged)
directionManager();
// If the game is started, poll the buttons
if (started)
buttonManager();
// Set the parameter TRUE for debugging purposes
printPosition(FALSE);
}
i2cCommandManager();
if (!digitalRead(START_PIN))
{
if (!startButtonCounterStarted)
{
startAllMotors();
started = 1;
succeed = 0;
digitalWrite(STARTED_PIN, started);
digitalWrite(SUCCEED_PIN, succeed);
motor1Started = 1;
motor2Started = 1;
doorUnlocked = FALSE;
digitalWrite(DOOR_PIN, LOW);
Serial.println("Started by pin");
startButtonCounterStarted = TRUE;
startButtonCounter = 0;
}
}
}
ISR(TIMER1_COMPA_vect)
{
Timer1_ISR();
}
ISR(PCINT2_vect)
{
readEncoder();
}
As I said before, I copied/pasted the sketch in Arduino IDE and it compiles without any errors with this tool. When trying to compile with Atmel Studio, I tried to build/rebuild the solution, the sketch itself, with and without cleaning first, still get the error.
Here is a solution explorer printscreen :
Any clue would be appreciated !
Best regards.
Eric
Related
how do i call a function in loop from another function in void loop arduino
#define CLK 2 #define DT 3 #define SW 4 #include <EEPROM.h> #include <Wire.h> #include <LiquidCrystal_PCF8574.h> LiquidCrystal_PCF8574 lcd(0x27); int counter = 0; int currentStateCLK; int lastStateCLK; int lastCLK,cnt=0,btnState,lastPress=0; String currentDir =""; unsigned long lastButtonPress = 0; char *mainmenu[] ={"SET MODE","SET TEMP","SET HUMD","SERVO","RESET"}; char *setmode[] ={"INCUBATOR","HATCHER","BACK"}; void setup() { // Set encoder pins as inputs Wire.begin(); Wire.beginTransmission(0x27); pinMode(CLK,INPUT); pinMode(DT,INPUT); pinMode(SW, INPUT_PULLUP); lcd.begin(16, 2); lcd.setBacklight(255); lcd.home(); lcd.clear(); Serial.begin(9600); lastStateCLK = digitalRead(CLK); delay(100); if(EEPROM_READ(0)==NULL){ SET_MODE(); } Serial.print(EEPROM_READ(0)); } void loop(){ disp(); rot(); } void disp(){ lcd.setCursor(0,0); lcd.print(" KGF"); } void rot() { int lim=sizeof(mainmenu)/2; Serial.print(lim); currentStateCLK = digitalRead(CLK); if (currentStateCLK != lastStateCLK && currentStateCLK == 1){ lcd.clear(); lcd.setCursor(0, 1); if (digitalRead(DT) != currentStateCLK) { counter --; if(counter<0){ counter=lim-1; } } else { // Encoder is rotating CW so increment counter ++; if(counter>lim-1){ counter=0; } lcd.print(mainmenu[counter]); } lastStateCLK = currentStateCLK; int btnState = digitalRead(SW); if (btnState == LOW) { //if 50ms have passed since last LOW pulse, it means that the //button has been pressed, released and pressed again if (millis() - lastButtonPress > 50) { if(counter==0){ SET_MODE(); } } } lastButtonPress = millis(); } delay(1); } void SET_MODE(){ int lim=sizeof(setmode)/2; int currentCLK = digitalRead(CLK); if (currentCLK != lastCLK && currentCLK == 1){ lcd.clear(); lcd.setCursor(0, 1); if (digitalRead(DT) != currentCLK) { cnt --; if(cnt<0){ cnt=lim-1; } } else { // Encoder is rotating CW so increment cnt ++; if(cnt>lim-1){ cnt=0; } } lcd.print(setmode[cnt]); } lastCLK = currentCLK; btnState = digitalRead(SW); if (btnState == LOW) { //if 50ms have passed since last LOW pulse, it means that the //button has been pressed, released and pressed again if (millis() - lastButtonPress > 50) { if(setmode[cnt]=="BACK"){ exit(0); } lcd.clear(); lcd.setCursor(0, 1); EEPROM_WRITE(0,setmode[cnt]); lcd.print("DONE"); } lastPress = millis(); } delay(1); } void EEPROM_WRITE(int addrOffset, const String &strToWrite) { byte len = strToWrite.length(); EEPROM.write(addrOffset, len); for (int i = 0; i < len; i++) { EEPROM.write(addrOffset + 1 + i, strToWrite[i]); } } String EEPROM_READ(int addrOffset) { int newStrLen = EEPROM.read(addrOffset); char data[newStrLen + 1]; for (int i = 0; i < newStrLen; i++) { data[i] = EEPROM.read(addrOffset + 1 + i); } data[newStrLen] = '\0'; return String(data); } I want to call the SET_MODE() function in the loop from rot() function, I am building a menu based program so the SET MODE menu should redirect to the SET_MODE() function, and as I will be adding more menu and sub-menus how can I perform this task. The SET_MODE() function doesn't work in loop I do not know why, it only works when I all it under void loop() directly.
Trying to write character from Arduino pin to Putty
So, i am writing a code to send a character (8 data-bits) and a stop bit to Putty using the Arduino timer 1 interrupt. When I try to send a character it shows something in Putty, so it does send, but not the character I am sending. I have searched for all sorts of documentation but i can't seem to find what i need, also I don't know what I'm doing wrong. Code: #define Fosc 16000000 int rxPin = 7; int txPin = 8; int dataBits = 0; uint8_t txBuffer; void setup() { Serial.begin(9600); pinMode(txPin, OUTPUT); pinMode(rxPin, INPUT); setupInterrupts(9600); } void loop() { ReadMessage(); } void setupInterrupts(long baud) { long cmr = ((Fosc / (64 * baud)) - 1); //compare match register noInterrupts(); TCCR1A = 0; TCCR1B = 0; TCNT1 = 0; //counter value to 0 OCR1A = cmr; TCCR1B |= (1 << WGM12); // CTC mode TCCR1B |= (1 << CS11) | (1 << CS10); // Set bits for 64 prescaler //TIMSK1 = _BV(OCIE1A); //attach interrupts(); } ISR(TIMER1_COMPA_vect) { transmit(); } void transmit() { if (dataBits < 8) { if (txBuffer & 0b1) { digitalWrite(txPin, HIGH); } else { digitalWrite(txPin, LOW); } txBuffer >>= 1; } dataBits++; if (dataBits == 9) { dataBits = 0; digitalWrite(txPin, HIGH); TIMSK1 &= ~_BV(OCIE1A); //detach } } bool getParity(unsigned int n) { bool parity = 0; while (n) { parity = !parity; n = n & (n - 1); } return parity; } int incomingByte; void ReadMessage() { if (Serial.available() > 0) { incomingByte = Serial.read(); char receivedCharacter = (char) incomingByte; txBuffer = receivedCharacter; Serial.println((char)txBuffer); TIMSK1 = _BV(OCIE1A); //attach } } Putty Output
Arduino NRF24l01 RC sends nothing
I'm trying to execute following source on my RC transmitter and receiver which uses NRF24 module. Today i uploaded same sketch as i did half year ago and it stopped receiving any data from transmitter, nothing is printed in DEBUG_PRINT sections. On transmitter NRF24 is connected to 7, 8. On receiver NRF24 is connected to 9, 10. Wiring checked 7 times, correct, power supply of the receiver is 7.4V to the VIN, power supply for the transmitter is USB source. Running on the arduino nano. Source for transmitter is: // Flash for self-diy NRF24lo* transmiter controller. // 6 buttons, 4-way sticks, based on CX-10c controller. #include <EEPROM.h> #include <SPI.h> #include "RF24.h" #define DEBUG_PRINT // #define DEBUG_PRINT_RAW #ifdef DEBUG_PRINT #include <printf.h> #endif // IO mappings #define STICK0 A3 #define STICK1 A2 #define STICK2 A0 #define STICK3 A1 #define BTN0 3 #define BTN1 6 #define BTN2 5 #define BTN3 4 #define BTN4 9 #define BTN5 A4 #define STLED 2 // Optional moddings #define BTN_LONG_PRESS 1000 #define LED_ST_OFF 0 #define LED_ST_CONST 1 #define LED_ST_FLASH 2 #define LED_ST_FAST_FLASH 3 #define LED_ST_FLASH_TIME 250 #define LED_ST_FAST_FLASH_TIME 100 #define LED_POWER 150 // Package types #define PACKAGE_STICKS 3 #define PACKAGE_BUTTON 5 #define PACKAGE_PING 7 #define PACKAGE_TIMEOUT 100 // Amount of packages should be dropped sequently to detect disconnect #define TX_DROP_EDGE 16 // Long press stick 0 to start calibration, long press to stop // Struct with min/max calibration values struct STICK_CALIBRATION { int stmx[4]; int stmn[4]; }; // Struct with info of button presses struct BTN_STATE { int press[6]; unsigned long time[6]; // Used in long press to avoid multiple pressing int acted[6]; }; // Struct with state of flashing/idle/working LED // FLASH --> CONST/OFF // FAST_FLASH --> CONST/OFF struct LED_STATE { // Previous type (for FLASH return to OFF/CONST state) int ptype; // Type of operation int type; // ON/OFF int state; // Time since action unsigned long time; // Count of flashes int count; }; // Sender package type. // Contains type and values for button or values for sticks struct Package { int type; union { struct { int number; int lpress; int dummy[2]; } button; struct { int sticks[4]; } sticks; } data; }; // Info of sticks calibration STICK_CALIBRATION calibration; bool calibration_mode = 0; int sticks[4]; // When entering lock mode, stick data is not updating from input bool lock_mode = 0; // info of buttons states BTN_STATE buttons; LED_STATE led_state; // Use NRF24lo1 transmitter on pins 7, 8 RF24 radio(7, 8); byte addresses[][6] = { "TRAAA", "REEEE" }; // Amount of sequently dropped packages. Used to detect disconnect int tx_dropped = 0; // Used to prevent longpress repeat // On long press button could be used as sticky press function, // to avoid button sticking and long press act once during while push down, // use this function to mark button as acted void btn_act(int nubmer); // Called on button press/longpress void btn_action(int number, int lpress); // Set led ON/OFF with change of state flag void led_set_state(int state); // Set led action type (FLAST, CONST, e.t.c.) void led_set(int type, int count); // Sends single package with given amount of attempts. // Allows waiting for responce of receiver. The response should be 0. // Returns 1 on success, 0 on failture. int send_package(byte* pack, int size); void setup() { #ifdef DEBUG_PRINT Serial.begin(115200); #endif // Set up transmitter radio.begin(); radio.setChannel(77); radio.enableAckPayload(); radio.setPALevel(RF24_PA_MAX); radio.openWritingPipe(addresses[1]); radio.openReadingPipe(1, addresses[0]); #ifdef DEBUG_PRINT printf_begin(); radio.printDetails(); #endif // Read calibration values byte* cal_struct = (byte*) &calibration; for (int i = 0; i < sizeof(STICK_CALIBRATION); ++i) cal_struct[i] = EEPROM.read(i); #ifdef DEBUG_PRINT Serial.println("CALIBRATION: "); for (int i = 0; i < 4; ++i) { Serial.print('('); Serial.print(calibration.stmn[i]); Serial.print(", "); Serial.print(calibration.stmx[i]); Serial.print(") "); } Serial.println(); #endif buttons = {{0,0,0,0,0,0}, {0,0,0,0,0,0}, {0,0,0,0,0,0}}; // Clear LED state led_state.ptype = 0; led_state.type = 0; led_state.state = 0; led_state.time = 0; led_state.count = 0; // Prepare pinout pinMode(STLED, OUTPUT); pinMode(STICK0, INPUT_PULLUP); pinMode(STICK1, INPUT_PULLUP); pinMode(STICK2, INPUT_PULLUP); pinMode(STICK3, INPUT_PULLUP); pinMode(BTN0, INPUT_PULLUP); pinMode(BTN1, INPUT_PULLUP); pinMode(BTN2, INPUT_PULLUP); pinMode(BTN3, INPUT_PULLUP); pinMode(BTN4, INPUT_PULLUP); pinMode(BTN5, INPUT_PULLUP); } void loop() { // Read sticks & map to calibration if (!lock_mode) { sticks[0] = analogRead(STICK0); sticks[1] = analogRead(STICK1); sticks[2] = 1024 - analogRead(STICK2); sticks[3] = 1024 - analogRead(STICK3); } // Read stick buttons int rbtn[6]; rbtn[0] = !digitalRead(BTN0); rbtn[1] = !digitalRead(BTN1); // read optional buttons rbtn[2] = !digitalRead(BTN2); rbtn[3] = !digitalRead(BTN3); rbtn[4] = !digitalRead(BTN4); rbtn[5] = !digitalRead(BTN5); #ifdef DEBUG_PRINT #ifdef DEBUG_PRINT_RAW // Debug out Serial.print(sticks[0]); Serial.print(' '); Serial.print(sticks[1]); Serial.print(' '); Serial.print(sticks[2]); Serial.print(' '); Serial.print(sticks[3]); Serial.print(' '); Serial.print(rbtn[0]); Serial.print(' '); Serial.print(rbtn[1]); Serial.print(' '); Serial.print(rbtn[2]); Serial.print(' '); Serial.print(rbtn[3]); Serial.print(' '); Serial.print(rbtn[4]); Serial.print(' '); Serial.print(rbtn[5]); Serial.print(' '); Serial.println(); #endif #endif // Map to calibration if (!calibration_mode && !lock_mode) { sticks[0] = map(sticks[0], calibration.stmn[0], calibration.stmx[0], 0, 1023); sticks[1] = map(sticks[1], calibration.stmn[1], calibration.stmx[1], 0, 1023); sticks[2] = map(sticks[2], calibration.stmn[2], calibration.stmx[2], 0, 1023); sticks[3] = map(sticks[3], calibration.stmn[3], calibration.stmx[3], 0, 1023); } // Check buttons states and update timings for (int i = 0; i < 6; ++i) { if (buttons.press[i] && !rbtn[i]) { // Button released if (!buttons.acted[i]) btn_action(i, (millis() - buttons.time[i]) > BTN_LONG_PRESS); buttons.press[i] = 0; buttons.time[i] = 0; } else if (buttons.press[i]) { // Button keeps down if ((millis() - buttons.time[i]) > BTN_LONG_PRESS && !buttons.acted[i]) { // Toggle long press btn_action(i, 1); // buttons.press[i] = 0; buttons.time[i] = 0; } } else if (rbtn[i]) { // Button pressed buttons.press[i] = 1; buttons.acted[i] = 0; buttons.time[i] = millis(); } } // Update LED if (led_state.type == LED_ST_FLASH && (led_state.time + LED_ST_FLASH_TIME) < millis() || led_state.type == LED_ST_FAST_FLASH && (led_state.time + LED_ST_FAST_FLASH_TIME) < millis()) { // Flash period done if (!led_state.state) { // Count cycle as finished, try to begin another one --led_state.count; if (led_state.count <= 0) { // Flashing cycles is done led_state.type = led_state.ptype; led_set_state(led_state.type == LED_ST_CONST); } else { // Turn led ON again, begin next flash cycle led_state.time = millis(); led_set_state(1); } } else { // Just turn the led OFF led_state.time = millis(); led_set_state(0); } } // Update led flashing if (led_state.type != LED_ST_FLASH && led_state.type != LED_ST_FAST_FLASH) { if (calibration_mode) led_set(LED_ST_FAST_FLASH, 4); else { // Update led lighting if (lock_mode) led_set(LED_ST_CONST, 0); else led_set(LED_ST_OFF, 0); } } // If !paired if (calibration_mode) { for (int i = 0; i < 4; ++i) { if (calibration.stmn[i] > sticks[i]) calibration.stmn[i] = sticks[i]; if (calibration.stmx[i] < sticks[i]) calibration.stmx[i] = sticks[i]; } } else { // Sending package with sticks Package pack; pack.type = PACKAGE_STICKS; pack.data.sticks.sticks[0] = sticks[0]; pack.data.sticks.sticks[1] = sticks[1]; pack.data.sticks.sticks[2] = sticks[2]; pack.data.sticks.sticks[3] = sticks[3]; bool result = send_package((byte*) &pack, sizeof(Package)); if (!result) { if (tx_dropped > TX_DROP_EDGE && led_state.type != LED_ST_FLASH && led_state.type != LED_ST_FAST_FLASH) led_set(LED_ST_FLASH, 4); #ifdef DEBUG_PRINT Serial.println("TX failed"); #endif } } } int send_package(byte* pack, int size) { if (!radio.write(pack, size)) { ++tx_dropped; return 0; } else { byte payload; if (radio.isAckPayloadAvailable()) { radio.read(&payload, sizeof(byte)); tx_dropped = 0; return 1; } ++tx_dropped; return 0; } }; void led_set_state(int state) { if (led_state.state && !state) { digitalWrite(STLED, 0); led_state.state = !led_state.state; } else if (!led_state.state && state) { analogWrite(STLED, LED_POWER); led_state.state = !led_state.state; } }; void led_set(int type, int count) { if (type == LED_ST_CONST || type == LED_ST_OFF) { led_set_state(type == LED_ST_CONST); led_state.type = type; } else { // if was flashing --> rewrite // if was constant --> move type to ptype & do flashing if (led_state.type == LED_ST_CONST || led_state.type == LED_ST_OFF) led_state.ptype = led_state.type; led_state.type = type; led_state.count = count; led_state.time = millis(); led_set_state(1); } }; void btn_act(int number) { buttons.acted[number] = 1; }; // Override calls for button presses void btn_action(int number, int lpress) { #ifdef DEBUG_PRINT Serial.print("Press for "); Serial.println(number); #endif switch(number) { // calibration case 0: { // press = ? // Lpress = calibration mode if (lpress) { if (calibration_mode && !lock_mode) { // Write calibration values byte* cal_struct = (byte*) &calibration; for (int i = 0; i < sizeof(STICK_CALIBRATION); ++i) EEPROM.write(i, cal_struct[i]); calibration_mode = 0; #ifdef DEBUG_PRINT Serial.println("NEW CALIBRATION: "); for (int i = 0; i < 4; ++i) { Serial.print('('); Serial.print(calibration.stmn[i]); Serial.print(", "); Serial.print(calibration.stmx[i]); Serial.print(") "); } Serial.println(); #endif } else { for (int i = 0; i < 4; ++i) { calibration.stmn[i] = 1024; calibration.stmx[i] = 0; } calibration_mode = 1; } } break; } case 1: { // press = ? // Lpress = lock mode if (lpress) { lock_mode = !lock_mode; } break; } } led_set(LED_ST_FAST_FLASH, 2); btn_act(number); Package pack; pack.type = PACKAGE_BUTTON; pack.data.button.number = number; pack.data.button.lpress = lpress; bool result = send_package((byte*) &pack, sizeof(Package)); #ifdef DEBUG_PRINT if (!result) Serial.println("Button TX failed"); #endif }; Source for receiver is: // Flash for self-diy NRF24lo* receiver controller. // 6 buttons, 4-way sticks. #include <Servo.h> #include <SPI.h> #include "RF24.h" #define DEBUG_PRINT #ifdef DEBUG_PRINT #include <printf.h> #endif // IO mappings #define CONNECT_0 2 #define CONNECT_1 3 #define CONNECT_2 4 #define CONNECT_3 5 #define CONNECT_4 6 #define CONNECT_5 7 #define CONNECT_6 8 #define CONNECT_A0 A0 #define CONNECT_A1 A1 #define CONNECT_A2 A2 #define CONNECT_A3 A3 #define CONNECT_A4 A4 #define CONNECT_A5 A5 // A6, A7 on nano are only analog input #define CONNECT_A6 A6 #define CONNECT_A7 A7 // Inverters for sticks #define INVERT_STICK0 0 #define INVERT_STICK1 0 #define INVERT_STICK2 0 #define INVERT_STICK3 0 // Mappings for sticks #define SERVO_MAP_STICK0 0, 180 #define SERVO_MAP_STICK1 0, 180 #define SERVO_MAP_STICK2 0, 180 #define SERVO_MAP_STICK3 60, 120 #define ANALOG_MAP_STICK0 0, 255 #define ANALOG_MAP_STICK1 0, 255 #define ANALOG_MAP_STICK2 0, 255 #define ANALOG_MAP_STICK3 0, 255 // Optional moddings // Package types #define PACKAGE_STICKS 3 #define PACKAGE_BUTTON 5 #define PACKAGE_PING 7 // Used to detect disconnect from the controller #define CONNECTION_TIMEOUT 100 // Mpdes for output of the motor // #define MODE_2_DIGITAL_1_ANALOG #define MODE_2_ANALOG // Receiver package struct. // Contains type and values for button or values for sticks struct Package { int type; union { struct { int number; int lpress; // Used to complete size of the package. // Without it, payload is not sending for sticks. int dummy[2]; } button; struct { int sticks[4]; } sticks; } data; }; // Describes state of a single buttons on controller // Single press -> 1 // Second press -> 0 struct Button { bool state; bool lstate; }; // Use NRF24lo1 transmitter on pins 7, 8 RF24 radio(9, 10); byte addresses[][6] = { "TRAAA", "REEEE" }; // Used to detect timed disconnection from the controller unsigned long last_receive_time; bool disconnected; // Servos mapped to sticks Servo servo[4]; // Buttons states Button buttons[6]; // Called on connection restored after drop void on_connection(); // Called on connection dropped void on_disconnection(); // Called on button state received void button_action(int button, int lpress); // Called on sticks state received void sticks_action(int sticks[4]); void setPWMNanofrequency(int freq) { TCCR2B = TCCR2B & 0b11111000 | freq; TCCR1B = TCCR1B & 0b11111000 | freq; } void setup() { #ifdef DEBUG_PRINT Serial.begin(115200); #endif // Set up receiver radio.begin(); radio.setChannel(77); //radio.setAutoAck(1); //radio.setRetries(0, 8); radio.enableAckPayload(); radio.setPALevel(RF24_PA_MAX); //radio.setCRCLength(RF24_CRC_8); radio.openWritingPipe(addresses[0]); radio.openReadingPipe(1, addresses[1]); #ifdef DEBUG_PRINT // Debugger output printf_begin(); radio.printDetails(); #endif radio.startListening(); // Init buttons with 0 buttons[0] = { 0, 0 }; buttons[1] = { 0, 0 }; buttons[2] = { 0, 0 }; buttons[3] = { 0, 0 }; buttons[4] = { 0, 0 }; buttons[5] = { 0, 0 }; // Set up pinout pinMode(CONNECT_0, OUTPUT); pinMode(CONNECT_2, OUTPUT); pinMode(CONNECT_3, OUTPUT); pinMode(CONNECT_4, OUTPUT); pinMode(CONNECT_5, OUTPUT); pinMode(CONNECT_6, OUTPUT); pinMode(CONNECT_A0, OUTPUT); pinMode(CONNECT_A1, OUTPUT); pinMode(CONNECT_A2, OUTPUT); pinMode(CONNECT_A3, OUTPUT); pinMode(CONNECT_A4, OUTPUT); pinMode(CONNECT_A5, OUTPUT); pinMode(CONNECT_A6, INPUT); pinMode(CONNECT_A7, INPUT); // setPWMNanofrequency(0x02); // Set up servos servo[0].attach(CONNECT_A4); // Remapped servos to leave three PWM pins servo[1].attach(CONNECT_A5); servo[2].attach(CONNECT_5); servo[3].attach(CONNECT_6); // Clear disconnect trigger last_receive_time = millis(); disconnected = 0; // Reset outputs digitalWrite(CONNECT_0, LOW); digitalWrite(CONNECT_2, LOW); digitalWrite(CONNECT_3, LOW); digitalWrite(CONNECT_4, LOW); digitalWrite(CONNECT_5, LOW); digitalWrite(CONNECT_6, LOW); digitalWrite(CONNECT_A0, LOW); digitalWrite(CONNECT_A1, LOW); digitalWrite(CONNECT_A2, LOW); digitalWrite(CONNECT_A3, LOW); digitalWrite(CONNECT_A4, LOW); digitalWrite(CONNECT_A5, LOW); // digitalWrite(CONNECT_A6, LOW); // digitalWrite(CONNECT_A7, LOW); } void loop() { byte payload = 13; radio.writeAckPayload(1, &payload, sizeof(byte)); if (radio.available()) { Package pack; radio.read((byte*) &pack, sizeof(Package)); // Update trigger last_receive_time = millis(); if (disconnected) on_connection(); disconnected = 0; switch(pack.type) { case PACKAGE_STICKS: { #ifdef DEBUG_PRINT Serial.print(pack.data.sticks.sticks[0]); Serial.print(' '); Serial.print(pack.data.sticks.sticks[1]); Serial.print(' '); Serial.print(pack.data.sticks.sticks[2]); Serial.print(' '); Serial.print(pack.data.sticks.sticks[3]); Serial.println(); #endif if (INVERT_STICK0) pack.data.sticks.sticks[0] = 1024 - pack.data.sticks.sticks[0]; if (INVERT_STICK1) pack.data.sticks.sticks[1] = 1024 - pack.data.sticks.sticks[1]; if (INVERT_STICK2) pack.data.sticks.sticks[2] = 1024 - pack.data.sticks.sticks[2]; if (INVERT_STICK3) pack.data.sticks.sticks[3] = 1024 - pack.data.sticks.sticks[3]; int ssticks[4]; ssticks[0] = map(pack.data.sticks.sticks[0], 0, 1023, SERVO_MAP_STICK0); ssticks[1] = map(pack.data.sticks.sticks[1], 0, 1023, SERVO_MAP_STICK1); ssticks[2] = map(pack.data.sticks.sticks[2], 0, 1023, SERVO_MAP_STICK2); ssticks[3] = map(pack.data.sticks.sticks[3], 0, 1023, SERVO_MAP_STICK3); int asticks[4]; asticks[0] = map(pack.data.sticks.sticks[0], 0, 1023, ANALOG_MAP_STICK0); asticks[1] = map(pack.data.sticks.sticks[1], 0, 1023, ANALOG_MAP_STICK1); asticks[2] = map(pack.data.sticks.sticks[2], 0, 1023, ANALOG_MAP_STICK2); asticks[3] = map(pack.data.sticks.sticks[3], 0, 1023, ANALOG_MAP_STICK3); #ifdef DEBUG_PRINT Serial.print("Servo data: "); Serial.print(ssticks[0]); Serial.print(' '); Serial.print(ssticks[1]); Serial.print(' '); Serial.print(ssticks[2]); Serial.print(' '); Serial.print(ssticks[3]); Serial.println(); Serial.print("Analog data: "); Serial.print(asticks[0]); Serial.print(' '); Serial.print(asticks[1]); Serial.print(' '); Serial.print(asticks[2]); Serial.print(' '); Serial.print(asticks[3]); Serial.println(); #endif sticks_action(pack.data.sticks.sticks, ssticks, asticks); break; } case PACKAGE_BUTTON: { #ifdef DEBUG_PRINT Serial.print(pack.data.button.number); Serial.print(' '); Serial.print(pack.data.button.lpress); Serial.println(); #endif // Update states of the buttons if (pack.data.button.lpress) buttons[pack.data.button.number].lstate = !buttons[pack.data.button.number].lstate; else buttons[pack.data.button.number].state = !buttons[pack.data.button.number].state; button_action(pack.data.button.number, pack.data.button.lpress); break; } } } else if (!disconnected && millis() - last_receive_time > CONNECTION_TIMEOUT) { disconnected = 1; on_disconnection(); } } void on_connection() { }; void on_disconnection() { // servo[0].write(0); // servo[1].write(0); // servo[2].write(0); // servo[3].write(0); // analogWrite(CONNECT_A0, 0); // analogWrite(CONNECT_A1, 0); // analogWrite(CONNECT_A2, 0); // analogWrite(CONNECT_A3, 0); #ifdef MODE_2_DIGITAL_1_ANALOG digitalWrite(CONNECT_1, LOW); digitalWrite(CONNECT_2, LOW); digitalWrite(CONNECT_3, LOW); #endif #ifdef MODE_2_ANALOG digitalWrite(CONNECT_3, LOW); digitalWrite(CONNECT_4, LOW); digitalWrite(CONNECT_0, LOW); #endif }; void button_action(int button, int lpress) { switch (button) { case 0: case 1: break; case 2: { digitalWrite(CONNECT_A0, buttons[button].state); break; } case 3: { digitalWrite(CONNECT_A1, buttons[button].state); break; } case 4: { digitalWrite(CONNECT_A2, buttons[button].state); break; } case 5: { digitalWrite(CONNECT_A3, buttons[button].state); break; } } }; void sticks_action(int sticks[4], int ssticks[4], int asticks[4]) { servo[0].write(ssticks[0]); servo[1].write(ssticks[1]); servo[2].write(ssticks[2]); servo[3].write(ssticks[3]); // analogWrite(CONNECT_A0, asticks[0]); // analogWrite(CONNECT_A1, asticks[1]); // analogWrite(CONNECT_A2, asticks[2]); // analogWrite(CONNECT_A3, asticks[3]); // Control H-Bridge over 3, 4 outputs with right stick int value = (sticks[2] > 500) ? (sticks[2] - 500) : (sticks[2] < 480) ? (480 - sticks[2]) : (0); if (value < 500) value = map(value, 0, 480, 0, 255); else value = map(value, 0, 1023 - 500, 0, 255); value = (value > 255) ? 255 : (value < 0) ? 0 : value; // connecting 2 digital pins as HIGH,LOW / LOW,HIGH and analog as speed value (used in bts79603 bridge) #ifdef MODE_2_DIGITAL_1_ANALOG if (sticks[2] > 500) { digitalWrite(CONNECT_1, HIGH); digitalWrite(CONNECT_2, LOW); analogWrite(CONNECT_3, value); } else if (sticks[2] < 480) { digitalWrite(CONNECT_1, LOW); digitalWrite(CONNECT_2, HIGH); analogWrite(CONNECT_3, value); } else { digitalWrite(CONNECT_1, LOW); digitalWrite(CONNECT_2, LOW); analogWrite(CONNECT_3, 0); } #endif // connecting 2 analog pins to simple H-Bridge #ifdef MODE_2_ANALOG analogWrite(CONNECT_3, sticks[2] > 500 ? value : 0); analogWrite(CONNECT_4, sticks[2] < 480 ? value : 0); analogWrite(CONNECT_0, sticks[2] > 500 || sticks[2] < 480); #endif }; Transmitter printDetails output: STATUS = 0x0e RX_DR=0 TX_DS=0 MAX_RT=0 RX_P_NO=7 TX_FULL=0 RX_ADDR_P0-1 = 0x4141415254 0x4545454552 RX_ADDR_P2-5 = 0xc3 0xc4 0xc5 0xc6 TX_ADDR = 0x4141415254 RX_PW_P0-6 = 0x20 0x20 0x00 0x00 0x00 0x00 EN_AA = 0x3f EN_RXADDR = 0x03 RF_CH = 0x4d RF_SETUP = 0x07 CONFIG = 0x0e DYNPD/FEATURE = 0x00 0x00 Data Rate = 1MBPS Model = nRF24L01+ CRC Length = 16 bits PA Power = PA_MAX Receiver printDetails output: STATUS = 0x0e RX_DR=0 TX_DS=0 MAX_RT=0 RX_P_NO=7 TX_FULL=0 RX_ADDR_P0-1 = 0x4545454552 0x4141415254 RX_ADDR_P2-5 = 0xc3 0xc4 0xc5 0xc6 TX_ADDR = 0x4545454552 RX_PW_P0-6 = 0x20 0x20 0x00 0x00 0x00 0x00 EN_AA = 0x3f EN_RXADDR = 0x02 RF_CH = 0x4d RF_SETUP = 0x07 CONFIG = 0x0e DYNPD/FEATURE = 0x00 0x00 Data Rate = 1MBPS Model = nRF24L01+ CRC Length = 16 bits PA Power = PA_MAX Code used
Following code on receiver caused IO break. pinMode(CONNECT_A6, INPUT); pinMode(CONNECT_A7, INPUT); A6, A7 pins DOES NOT support mode change and this issue made NRF24 connection to fail.
How can I adjust cursor position without changing screens?
I have a project I'm working on with an LCD screen, two buttons, and a potentiometer, it's a binary calculator. When I reach screenState == 3 I am attempting to change the digits so i can keep track of them and add an 8 bit number with another 8 bit number, while tracking overflow. However, whenever I begin to use the button which the input == 0 it moves the cursor, and then my next button cycles through the screens again. Input == 0 should only change the value between 0 and 1 for whatever lcd.cursor value I'm. How can i adjust that one value without changing screens? #include <LiquidCrystal.h> LiquidCrystal lcd(11, 10, 5, 4, 3, 2); const int numInputs = 2; const int inputPins[numInputs] = {13, 12}; // tracks screen state int screenState = 0; int prevScreenState = 0; int binaryValue = 0; // tracks if we are on the right screen to acceptInput and if our value is 0 or 1 bool canAcceptInput = false; bool valIsZero = false; int inputState[numInputs]; int lastInputState[numInputs] = {LOW,LOW}; bool inputFlags[numInputs] = {LOW,LOW}; int inputCounter[numInputs]; int cursorPosX = 0; int cursorPosY = 0; int blinkingPosX = cursorPosX; int blinkingPosY = cursorPosY; unsigned long lastDebounceTime[numInputs] = {0,0}; long debounceDelay = 50; void setup() { for(int i = 0; i < numInputs; i++) { pinMode(inputPins[i], INPUT); digitalWrite(inputPins[i], HIGH); // pull-up 20k } Serial.begin(9600); lcd.begin(16, 2); } void loop() { setInputFlags(); resolveInputFlags(); } void setInputFlags() { for(int i = 0; i < numInputs; i++) { int reading = digitalRead(inputPins[i]); if (reading != lastInputState[i]) { lastDebounceTime[i] = millis(); } if ((millis() - lastDebounceTime[i]) > debounceDelay) { if (reading != inputState[i]) { inputState[i] = reading; if (inputState[i] == HIGH) { inputFlags[i] = HIGH; } } } lastInputState[i] = reading; } } void resolveInputFlags() { for(int i = 0; i < numInputs; i++) { if(inputFlags[i] == HIGH) { // Input Toggle Logic // all invoked upon bttn press inputCounter[i]++; updateScreenState(i); printString(i); inputFlags[i] = LOW; } } } void updateScreenState(int input) { // input 0 = State 0 and 1 if(input == 0) { if(screenState > 2 & screenState < 19) { canAcceptInput = true; binaryValue = 1; updateScreenValues(); } else if (screenState == 1) { //screenState = 0; binaryValue = 0; updateScreenValues(); } else { //screenState = 2; binaryValue = 1; } // input 1 = State 2 to 6 }else if(input == 1) { // we have 20 max screen states, this cycles through them using button 2 if(screenState == 0 || screenState == 1 || screenState > 19) { screenState = 2; updateScreen(); }else{ screenState++; updateScreen(); } } } void setCursorValues( int cursorX, int cursorY) { lcd.setCursor(cursorX, cursorY); cursorPosX = cursorX; cursorPosY = cursorY; } void updateScreenValues() { if(canAcceptInput == true) { if(binaryValue == 0 ){ lcd.print("0"); } if(binaryValue == 1) { lcd.print("1"); binaryValue = 0; } } } // void update ----------------------------------------------------------------------------- void updateScreen() { // welcome screen ----------------------------- if(screenState == 2){ canAcceptInput = false; lcd.clear(); setCursorValues(0, 0); lcd.print("Welcome Screen"); setCursorValues(0, 1); lcd.print("Press Bttn 1"); } // start of byte 1 screen ---------------------------------------------------------------- if(screenState == 3){ canAcceptInput = true; lcd.clear(); setCursorValues(0, 0); lcd.print("Byte 1 Screen"); setCursorValues(0, 1); lcd.print(" 0000 0000 "); //move cursor to MSD and blink setCursorValues(3, 1); lcd.blink(); } //if screenState changes, so will the cursorValues----------- if(screenState == 4) { setCursorValues(4, 1); } if(screenState == 5) { setCursorValues(5, 1); } if(screenState == 6) { setCursorValues(6, 1); } if(screenState == 7) { setCursorValues(9, 1); } if(screenState == 8) { setCursorValues(10, 1); } if(screenState == 9) { setCursorValues(11, 1); } if(screenState == 10) { setCursorValues(12, 1); } //start of byte 2 screen ------------------------------------------------------- if(screenState == 11){ lcd.clear(); setCursorValues(0, 0); lcd.print("Byte 2 Screen"); setCursorValues(0, 1); lcd.print(" 0000 0000 "); setCursorValues(3, 1); lcd.blink(); } //if screenState changes, so will the cursorValues----------- if(screenState == 12) { setCursorValues(4, 1); } if(screenState == 13) { setCursorValues(5, 1); } if(screenState == 14) { setCursorValues(6, 1); } if(screenState == 15) { setCursorValues(9, 1); } if(screenState == 16) { setCursorValues(10, 1); } if(screenState == 17) { setCursorValues(11, 1); } if(screenState == 18) { setCursorValues(12, 1); } if(screenState == 19){ lcd.clear(); setCursorValues(0, 0); lcd.print("Solution Screen"); lcd.noCursor(); } if(screenState == 20){ lcd.clear(); setCursorValues(0, 0); lcd.print("Contrast Screen"); } } void printString(int output) { Serial.print("Input "); Serial.print(output); Serial.print(" was pressed "); Serial.print(inputCounter[output]); Serial.println(" times."); Serial.print("screenState = "); Serial.println(screenState); Serial.print("binaryValue = "); Serial.println(binaryValue); Serial.print("cursorPosX = "); Serial.print(cursorPosX); Serial.print(" cursorPosY = "); Serial.println(cursorPosY); Serial.print('\n'); }
Detect multiple claps with clapping sensor (arduino nano)
For school I am making a clapping sensor with my arduino nano. I have found some code to detect if there are 2 claps (link). But now I want to modify the code so it can distinguish if I clapped 1,2 or 3 times. I have now changed the source to detect 1 or 2 claps. But now if I clap twice, always a one clap is detected before it sees the 2 claps. And i have totally no idea how to detect 3 claps. Can someone please help me with this problem? Code: #define signalToRelayPin 12 #define sensorPin 7 int lastSoundValue; int soundValue; long lastNoiseTime = 0; long currentNoiseTime = 0; long lastLightChange = 0; int relayStatus = HIGH; void setup() { pinMode(sensorPin, INPUT); pinMode(signalToRelayPin, OUTPUT); Serial.begin(115200); } struct DataBlockStruct meting1,meting2; void loop() { soundValue = digitalRead(sensorPin); currentNoiseTime = millis(); if (soundValue == 1) { // if there is currently a noise if ( (currentNoiseTime > lastNoiseTime + 200) && // to debounce a sound occurring in more than a loop cycle as a single noise (lastSoundValue == 0) && // if it was silent before (currentNoiseTime < lastNoiseTime + 800) && // if current clap is less than 0.8 seconds after the first clap (currentNoiseTime > lastLightChange + 1000) // to avoid taking a third clap as part of a pattern ) { relayStatus = !relayStatus; Serial.println("2 X CLAP"); } else { Serial.println("1 X CLAP"); } lastNoiseTime = currentNoiseTime; } lastSoundValue = soundValue; }
Try this snippet: #define signalToRelayPin 12 #define sensorPin 7 int lastSoundValue; int soundValue; long lastNoiseTime = 0; long currentNoiseTime = 0; long lastLightChange = 0; int relayStatus = HIGH; int clap_interval = 500; int claps = 0; void setup() { pinMode(sensorPin, INPUT); pinMode(signalToRelayPin, OUTPUT); Serial.begin(115200); } struct DataBlockStruct meting1,meting2; void loop() { soundValue = digitalRead(sensorPin); currentNoiseTime = millis(); if (soundValue == 1 && lastSoundValue == 0) { if (claps == 0) // allow first to register without much condition { claps = 1; lastNoiseTime = currentNoiseTime; } else { if (currentNoiseTime > lastNoiseTime + clap_interval) { claps++; lastNoiseTime = currentNoiseTime; relayStatus = !relayStatus; } } } else { if (currentNoiseTime > lastNoiseTime + 2 * clap_interval) // no claps for a longer duration time to print and/or reset clap { if (claps > 0) { Serial.print(claps); Serial.println(" CLAPS"); claps = 0; ///reset } } } //lastSoundValue = soundValue; delay(50); // delay polling }