I'm developing an Arduino project with push buttons. I need some action to be executed after a button is pressed. The problem is that whenever I use buttons on A6 and A7 pins, I get unexpected results like a button receives HIGH without being physically pressed. As long as I use digital pins with buttons, the code works just fine.
Could you please explain to me what may be the problem using A6 and A7 pins or maybe there is some tricky thing with these pins that I need to consider.
Thanks a lot!
Here is my code:
int buttonBack = A6;
int flagLeft, flagRight;
int eventBack;
int currentButtonStatus = 0;
unsigned long currentButtonStatusStart1;
unsigned long currentButtonStatusStart2;
unsigned long currentButtonStatusStart3;
const int delayFalse = 30;
const int delayLongSingleClick = 300;
const int delayDeltaDoubleClick = 200;
void setup() {
pinMode(buttonBack,INPUT);
}
void loop() {
int eventBack = changeButtonStatus();
if (eventBack > 0) {
if(eventBack == 1) { // single button press
flagLeft = 1; flagRight = 0;
// move motor to the left code goes here
}
if(eventBack == 4) {
// long button press
flagLeft = 0; flagRight = 1;
// move motor to the right code goes here
}
}
}
int changeButtonStatus() {
int event = 0;
int currentButtonClick = analogRead(buttonBack);
unsigned long timeButton = millis();
switch(currentButtonStatus) {
case 0:
if(currentButtonClick) {
currentButtonStatus = 1;
currentButtonStatusStart1 = millis();
} else {
}
break;
case 1:
if(currentButtonClick) {
if(timeButton - currentButtonStatusStart1 >= delayLongSingleClick) {
event = 3;
}
} else {
if(timeButton - currentButtonStatusStart1 < delayFalse) {
currentButtonStatus = 0;
event = 0;
} else if(timeButton - currentButtonStatusStart1 < delayLongSingleClick) {
currentButtonStatus = 2;
currentButtonStatusStart2 = millis();
} else {
currentButtonStatus = 0;
event = 4;
}
}
break;
case 2:
if(currentButtonClick) {
if(timeButton - currentButtonStatusStart2 < delayFalse) {
currentButtonStatus = 1;
} else {
currentButtonStatus = 3;
currentButtonStatusStart3 = millis();
}
} else {
if(timeButton - currentButtonStatusStart2 > delayDeltaDoubleClick) {
currentButtonStatus = 0;
event = 1;
}
}
break;
case 3:
if(currentButtonClick) {
} else {
if(timeButton - currentButtonStatusStart3 < delayFalse) {
} else {
event = 2;
currentButtonStatus = 0;
}
}
break;
}
return event;
}
A6 and A7 do not have GPIO capability. They can only be used as analog inputs which means that you will need to provide external pullups if you are attempting to emulate digital inputs with them.
Related
This is the code from someone for a water pump, I changed it to make a basic menu with the help of a YouTube video. Everything works fine, a lot fine, however, there is one problem.
To explain my problem, for example, when opening there is no problem, menu will be like
-Menu1
Menu2
and when I press once to down, menu will be
Menu1
-Menu2
Down again
Menu2
-Menu3
Until here everything is fine, when I click the up button it works well and go back like
-Menu2
Menu3
Then
-Menu1
Menu2
However if I press down at Menu3 and go for Menu4, I cannot go up again, I mean I can but Menu names not change, it always Menu3 and Menu 4, functions are work for 1 and 2 when I click but the menu always be like
Menu3
-Menu4
So that's the my problem, the code is below, so if you can help me, I would be really happy. This is my 1st week on my new work so I don't wanna be screw up :(
String menuItems[] = {"Menu1", "Menu2", "Menu3", "Menu4"};
// Navigation button variables
int readKey;
int button;
// Main Menu control variables:
int menuPage = 0;
int maxMenuPages = round(((sizeof(menuItems) / sizeof(String)) / 2) + .2);
int cursorPosition = 0;
int a;
int b;
// Creates 3 custom characters for the menu display
byte downArrow[8] = {
0b00100, // *
0b00100, // *
0b00100, // *
0b00100, // *
0b00100, // *
0b10101, // * * *
0b01110, // ***
0b00100 // *
};
byte upArrow[8] = {
0b00100, // *
0b01110, // ***
0b10101, // * * *
0b00100, // *
0b00100, // *
0b00100, // *
0b00100, // *
0b00100 // *
};
byte menuCursor[8] = {
B01000, // *
B00100, // *
B00010, // *
B00001, // *
B00010, // *
B00100, // *
B01000, // *
B00000 //
};
#include <Wire.h>
#include <LiquidCrystal.h>
// Setting the LCD shields pins
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
void setup() {
// Initializes serial communication
Serial.begin(9600);
// Initializes and clears the LCD screen
lcd.begin(16, 2);
lcd.clear();
// Creates the byte for the 3 custom characters
lcd.createChar(0, menuCursor);
lcd.createChar(1, upArrow);
lcd.createChar(2, downArrow);
}
void loop() {
mainMenuDraw();
drawCursor();
operateMainMenu();
}
// This function, for the MAIN menu, will generate the 2 menu items that can fit on the screen.
//They will change as you scroll through your menu.
//Up and down arrows will indicate your current menu position.
void mainMenuDraw() {
lcd.clear();
lcd.setCursor(1, 0);
lcd.print(menuItems[menuPage]);
lcd.setCursor(1,1);
lcd.print(menuItems[menuPage + 1]);
UpDnArrowDraw(menuPage, maxMenuPages);
}
void drawCursor() {
for (int x = 0; x < 2; x++) {
lcd.setCursor(0, x);
lcd.print(" ");
}
if (menuPage % 2 == 0) {
if (cursorPosition % 2 == 0) {
lcd.setCursor(0, 0);
lcd.write(byte(0));
}
if (cursorPosition % 2 != 0) {
lcd.setCursor(0, 1);
lcd.write(byte(0));
}
}
if (menuPage % 2 != 0) {
if (cursorPosition % 2 == 0) {
lcd.setCursor(0, 1);
lcd.write(byte(0));
}
if (cursorPosition % 2 != 0) {
lcd.setCursor(0, 0);
lcd.write(byte(0));
}
}
}
void operateMainMenu() {
int activeButton = 0;
while (activeButton == 0) {
int button;
readKey = analogRead(0);
if (readKey > 790) { // Wait here if no buttons pushed; read value should be max (~1023)
delay(50);
readKey = analogRead(0);
}
button = evaluateButton(readKey);
switch (button) {
case 0: // NO button returns as 0 there is no action taken
break;
case 1:
button = 0;
switch (cursorPosition) {
case 0:
menuItem1();
break;
case 1:
menuItem2();
break;
case 2:
menuItem3();
break;
case 3:
menuItem4();
break;
}
activeButton = 1;
mainMenuDraw();
drawCursor();
break;
case 2:
button = 0;
if (menuPage == 0) {
cursorPosition = cursorPosition - 1;
cursorPosition = constrain(cursorPosition, 0, ((sizeof(menuItems) / sizeof(String)) - 1));
}
if (menuPage % 2 != 0 and cursorPosition % 2 == 0) {
menuPage = menuPage - 1;
menuPage = constrain(menuPage, 0, maxMenuPages);
}
if (menuPage % 2 != 0 and cursorPosition % 2 != 0) {
menuPage = menuPage - 1;
menuPage = constrain(menuPage, 0, maxMenuPages);
}
cursorPosition = cursorPosition - 1;
cursorPosition = constrain(cursorPosition, 0, ((sizeof(menuItems) / sizeof(String)) - 1));
mainMenuDraw();
drawCursor();
activeButton = 1;
break;
case 3:
button = 0;
if (menuPage % 2 == 0 and cursorPosition % 2 != 0) {
menuPage = menuPage + 1;
menuPage = constrain(menuPage, 0, maxMenuPages);
}
if (menuPage % 2 != 0 and cursorPosition % 2 == 0) {
menuPage = menuPage + 1;
menuPage = constrain(menuPage, 0, maxMenuPages);
}
cursorPosition = cursorPosition + 1;
cursorPosition = constrain(cursorPosition, 0, ((sizeof(menuItems) / sizeof(String)) - 1));
mainMenuDraw();
drawCursor();
activeButton = 1;
break;
}
}
}
// This function is called whenever a button is pressed and determines which of the 5 buttons was pressed,
//based on the voltage drop across the buttons all hooked up to A0.
int evaluateButton(int x) {
int result = 0;
x = analogRead(0);
if (x < 800) {
delay(100);
x = analogRead(0); // Performs glitch filtering
}
if (x < 50) {
result = 1; // right button
} else if (x < 200) {
result = 2; // up button
} else if (x < 400) {
result = 3; // down button
} else if (x < 600) {
result = 4; // Left button
} else if (x < 800) {
result = 5; // Select button
}
return result;
}
void menuItem1() { // Function executes when you select the 1st item from main menu
int activeButton = 0;
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("SubMenu1");
while (activeButton == 0) {
int button; // Debounce
readKey = analogRead(0);
while (readKey > 790) { // Wait here if no buttons pushed; read value should be max (~1023)
delay(10);
readKey = analogRead(0);
}
button = evaluateButton(readKey);
switch (button) {
case 4: // This case will execute if the "back" button (e.g. LEFT) is pressed to go back to the Main menu
button = 0;
activeButton = 1;
break;
}
}
}
void menuItem2() { // Function executes when you select the 1st item from main menu
int activeButton = 0;
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("SubMenu2");
while (activeButton == 0) {
int button; // Debounce
readKey = analogRead(0);
while (readKey > 790) { // Wait here if no buttons pushed; read value should be max (~1023)
delay(10);
readKey = analogRead(0);
}
button = evaluateButton(readKey);
switch (button) {
case 4: // This case will execute if the "back" button (e.g. LEFT) is pressed to go back to the Main menu
button = 0;
activeButton = 1;
break;
}
}
}
void menuItem3() { // Function executes when you select the 1st item from main menu
int activeButton = 0;
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("SubMenu3");
while (activeButton == 0) {
int button; // Debounce
readKey = analogRead(0);
while (readKey > 790) { // Wait here if no buttons pushed; read value should be max (~1023)
delay(10);
readKey = analogRead(0);
}
button = evaluateButton(readKey);
switch (button) {
case 4: // This case will execute if the "back" button (e.g. LEFT) is pressed to go back to the Main menu
button = 0;
activeButton = 1;
break;
}
}
}
void menuItem4() { // Function executes when you select the 1st item from main menu
int activeButton = 0;
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("lak lak lak");
while (activeButton == 0) {
int button; // Debounce
readKey = analogRead(0);
while (readKey > 790) { // Wait here if no buttons pushed; read value should be max (~1023)
delay(10);
readKey = analogRead(0);
}
button = evaluateButton(readKey);
switch (button) {
case 4: // This case will execute if the "back" button (e.g. LEFT) is pressed to go back to the Main menu
button = 0;
activeButton = 1;
break;
}
}
}
// This function will generate the arrows that indicate which UP/DN buttons to press.
int UpDnArrowDraw(int a,int b) {
if (a == 0) { // IF for Up/Dn arrows
lcd.setCursor(15, 1);
lcd.write(byte(2)); // Display DN arrow only ( BYTE 1 is UP arrow; BYTE 2 is DN arrow)
lcd.setCursor(15, 0);
lcd.print(" ");
}
else if (a > 0 and a < b ) {
lcd.setCursor(15, 1);
lcd.write(byte(2));
lcd.setCursor(15, 0);
lcd.write(byte(1)); // Display both UP and DN arrow
}
else if (a == b) {
lcd.setCursor(15, 0);
lcd.write(byte(1)); // Display UP arrow only
lcd.setCursor(15, 1);
lcd.print(" ");
}
}
Well, changing the operateMainMenu part to this, miraculously solved everything lol, I'm gonna post it for who will use this code in future and dealing with this problem
void operateMainMenu() {
int activeButton = 0;
while (activeButton == 0) {
int button;
readKey = analogRead(0);
if (readKey > 790) { // Wait here if no buttons pushed; read value should be max (~1023)
delay(50);
readKey = analogRead(0);
}
button = evaluateButton(readKey);
switch (button) {
case 0: // NO button returns as 0 there is no action taken
break;
case 1:
button = 0;
switch (cursorPosition) {
case 0:
menuItem1();
break;
case 1:
menuItem2();
break;
case 2:
menuItem3();
break;
case 3:
menuItem4();
break;
}
activeButton = 1;
mainMenuDraw();
drawCursor();
break;
case 2:
button = 0;
cursorPosition = cursorPosition - 1;
cursorPosition = constrain(cursorPosition, 0, ((sizeof(menuItems) / sizeof(String)) - 1));
menuPage = menuPage - 1;
menuPage = constrain(menuPage, 0, maxMenuPages);
mainMenuDraw();
drawCursor();
activeButton = 1;
break;
case 3:
button = 0;
cursorPosition = cursorPosition + 1;
cursorPosition = constrain(cursorPosition, 0, ((sizeof(menuItems) / sizeof(String)) - 1));
menuPage = menuPage + 1;
menuPage = constrain(menuPage, 0, maxMenuPages);
mainMenuDraw();
drawCursor();
activeButton = 1;
break;
}
}
}
At the moment I am working on a code that should send a plateau to a certain position and back. The plateau is being moved by the stepper. My goal is to press '4' on the keyboard and that then the steppers moves to a certain position. However, I am not succeding in this. I am using AccelStepper and at the moment I have the following code:
#include <AccelStepper.h>
AccelStepper stepper(1, 5, 4);
int spd = 1000; // The current speed in steps/second
int sign = 1; // Either 1, 0 or -1
int buttonState = 0;
void setup()
{
Serial.begin(9600);
stepper.setMaxSpeed(1000);
stepper.setSpeed(1000);
}
void loop()
{
char c;
if (Serial.available()) {
c = Serial.read();
if (c == 'f') { // forward
sign = 1;
}
if (c == 'r') { // reverse
sign = -1;
}
if (c == 's') { // stop
sign = 0;
}
if (c == '1') { // super slow
spd = 100;
}
if (c == '2') { // medium
spd = 900;
}
if (c == '3') { // fast
spd = 1000;
}
if (c == '4') {
//not working, does anyone know how to do this?
stepper.moveTo(500);
}
stepper.setSpeed(sign * spd);
}
stepper.runSpeed();
}
Does anyone have tips or know how to achieve this?
Thanks is advance!
I have to read the incoming SMS on my gsm module SIM900 (which is connected to Arduino), and I want to print the sender number and message on to serial monitor.
I first configure gsm module with AT commands and Response() function will give me the response to AT commands.
as any SMS will be in the following pattern
+CMT: "[Mobile number]", "[Date and Time]"
[message body]
So, I first extract +CMT and after that I will take mobile number and atlast we have message body. The code I have used is
char RcvdMsg[200] = "";
int RcvdCheck = 0;
int RcvdConf = 0;
int index = 0;
int RcvdEnd = 0;
char MsgMob[15];
char MsgTxt[50];
int MsgLength = 0;
void Config() // This function is configuring our SIM900 module i.e. sending the initial AT commands
{
delay(1000);
Serial.print("ATE0\r");
Response();
Serial.print("AT\r");
Response();
Serial.print("AT+CMGF=1\r");
Response();
Serial.print("AT+CNMI=1,2,0,0,0\r");
Response();
}
void setup()
{
Serial.begin(9600);
Config();
}
void loop()
{
RecSMS();
}
void Response() // Get the Response of each AT Command
{
int count = 0;
Serial.println();
while(1)
{
if(Serial.available())
{
char data =Serial.read();
if(data == 'K'){Serial.println("OK");break;}
if(data == 'R'){Serial.println("GSM Not Working");break;}
}
count++;
delay(10);
if(count == 1000){Serial.println("GSM not Found");break;}
}
}
void RecSMS() // Receiving the SMS and extracting the Sender Mobile number & Message Text
{
if(Serial.available())
{
char data = Serial.read();
if(data == '+'){RcvdCheck = 1;}
if((data == 'C') && (RcvdCheck == 1)){RcvdCheck = 2;}
if((data == 'M') && (RcvdCheck == 2)){RcvdCheck = 3;}
if((data == 'T') && (RcvdCheck == 3)){RcvdCheck = 4;}
if(RcvdCheck == 4){RcvdConf = 1; RcvdCheck = 0;}
if(RcvdConf == 1)
{
if(data == '\n'){RcvdEnd++;}
if(RcvdEnd == 3){RcvdEnd = 0;}
RcvdMsg[index] = data;
index++;
if(RcvdEnd == 2){RcvdConf = 0;MsgLength = index-2;index = 0;}
if(RcvdConf == 0)
{
Serial.print("Mobile Number is: ");
for(int x = 4;x < 17;x++)
{
MsgMob[x-4] = RcvdMsg[x];
Serial.print(MsgMob[x-4]);
}
Serial.println();
Serial.print("Message Text: ");
for(int x = 46; x < MsgLength; x++)
{
MsgTxt[x-46] = RcvdMsg[x];
Serial.print(MsgTxt[x-46]);
}
Serial.println();
Serial.flush();
}
}
}
}
The problem of the code is
After receiving first SMS I am getting my mobile number and message body. After that I am only getting sender number printed on to my serial monitor but not the message body.
Where It has gone wrong. I could not understood.
Please help me.......Thanks in advance.
If it does work the first time, but not subsequent times it probably has to do with some variables not being reset. You declare all of your variables at the top of the file even though they are only needed in the RecSMS() function. Try moving the declarations to the top of RecSMS().
void RecSMS() {
char RcvdMsg[200] = "";
int RcvdCheck = 0;
int RcvdConf = 0;
int index = 0;
int RcvdEnd = 0;
char MsgMob[15];
char MsgTxt[50];
int MsgLength = 0;
if(Serial.available()) {
// Rest of the code goes here
Thankyou #Michael. I think this also solves the issue.
The problem I found in the code is, we are not resetting all the variables in RecSMS function. So to solve this keep this below code before the Serial.flush() statement.
RcvdCheck = 0;
RcvdConf = 0;
index = 0;
RcvdEnd = 0;
MsgMob[15];
MsgTxt[50];
MsgLength = 0;
This will solve the problem
I had purchased a microSD card shield from sparkfun and I wish to do data logging to read 2 MPU6050. I wished to have sampling frequency of 100Hz, so I came across one example from Greiman about lowlatencylogger. Using his example and SDFat library instead of SD library, I do can get very good sampling frequency, however, I cannot terminate the data logging at will.
I tried to add a switch to set a condition where if the arduino read the switch, then it will start truncating the file. But so far no result. So can anyone help me??
the code that I am using
#include <SPI.h>
#include <SdFat.h>
#include <SdFatUtil.h>
#include "Wire.h"
#include "I2Cdev.h"
#include "MPU6050.h"
//------------------------------------------------------------------------------
// User data functions. Modify these functions for your data items.
#include "UserDataType.h" // Edit this include file to change data_t.
MPU6050 mpu;
MPU6050 mpu_69 (0x69);
int switchPin = 6;
void setupData() {
#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
Wire.begin();
// set I2C 400 kHz
TWBR = (F_CPU/400000 - 16)/2;
Serial.println(F("Using Wire"));
#elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE
Fastwire::setup(400, true);
Serial.println(F("Using Fastwire"));
#endif
mpu.initialize();
mpu_69.initialize();
pinMode(switchPin,INPUT_PULLUP);
}
// Acquire a data record.
void acquireData(data_t* data) {
data->time = micros();
data->hs = analogRead(0);
data->to = analogRead(1);
mpu.getMotion6(&data->axr, &data->ayr, &data->azr,
&data->gxr, &data->gyr, &data->gzr);
mpu_69.getMotion6(&data->axl, &data->ayl, &data->azl,
&data->gxl, &data->gyl, &data->gzl);
}
// Print a data record.
void printData(Print* pr, data_t* data) {
pr->print(data->time);
pr->write(',');
pr->print(data->hs);
pr->write(',');
pr->print(data->to);
pr->write(',');
pr->print(data->axr);
pr->write(',');
pr->print(data->ayr);
pr->write(',');
pr->print(data->azr);
pr->write(',');
pr->print(data->gxr);
pr->write(',');
pr->print(data->gyr);
pr->write(',');
pr->print(data->gzr);
pr->write(',');
pr->print(data->axl);
pr->write(',');
pr->print(data->ayl);
pr->write(',');
pr->print(data->azl);
pr->write(',');
pr->print(data->gxl);
pr->write(',');
pr->print(data->gyl);
pr->write(',');
pr->println(data->gzl);
}
// Print data header.
void printHeader(Print* pr) {
pr->println(F("micros,heels,toeo,axshank,ayshank,azshank,gxshank,gyshank,gzshank,axankle,ayankle,azankle,gxankle,gyankle,gzankle"));
}
//==============================================================================
// Start of configuration constants.
//==============================================================================
//Interval between data records in microseconds.
const uint32_t LOG_INTERVAL_USEC = 10000;
//------------------------------------------------------------------------------
// Pin definitions.
//
// SD chip select pin.
const uint8_t SD_CS_PIN = 8;
//
// Digital pin to indicate an error, set to -1 if not used.
// The led blinks for fatal errors. The led goes on solid for SD write
// overrun errors and logging continues.
const int8_t ERROR_LED_PIN = -1;
//------------------------------------------------------------------------------
// File definitions.
//
// Maxrimum file size in blocks.
// The program creates a contiguous file with FILE_BLOCK_COUNT 512 byte blocks.
// This file is flash erased using special SD commands. The file will be
// truncated if logging is stopped early.
const uint32_t FILE_BLOCK_COUNT = 256000;
////////////////////////////
uint32_t const ERASE_SIZE = 262144L;
void logData() {
unsigned long timeout =0;
bool truncate=false;
uint32_t bgnBlock, endBlock;
// Allocate extra buffer space.
block_t block[BUFFER_BLOCK_COUNT];
block_t* curBlock = 0;
Serial.println();
// Find unused file name.
if (BASE_NAME_SIZE > 6) {
error("FILE_BASE_NAME too long");
}
while (sd.exists(binName)) {
if (binName[BASE_NAME_SIZE + 1] != '9') {
binName[BASE_NAME_SIZE + 1]++;
} else {
binName[BASE_NAME_SIZE + 1] = '0';
if (binName[BASE_NAME_SIZE] == '9') {
error("Can't create file name");
}
binName[BASE_NAME_SIZE]++;
}
}
// Delete old tmp file.
if (sd.exists(TMP_FILE_NAME)) {
Serial.println(F("Deleting tmp file"));
if (!sd.remove(TMP_FILE_NAME)) {
error("Can't remove tmp file");
}
}
// Create new file.
Serial.println(F("Creating new file"));
binFile.close();
if (!binFile.createContiguous(sd.vwd(),
TMP_FILE_NAME, 512 * FILE_BLOCK_COUNT)) {
error("createContiguous failed");
}
// Get the address of the file on the SD.
if (!binFile.contiguousRange(&bgnBlock, &endBlock)) {
error("contiguousRange failed");
}
// Use SdFat's internal buffer.
uint8_t* cache = (uint8_t*)sd.vol()->cacheClear();
if (cache == 0) {
error("cacheClear failed");
}
// Flash erase all data in the file.
Serial.println(F("Erasing all data"));
uint32_t bgnErase = bgnBlock;
uint32_t endErase;
while (bgnErase < endBlock) {
endErase = bgnErase + ERASE_SIZE;
if (endErase > endBlock) {
endErase = endBlock;
}
if (!sd.card()->erase(bgnErase, endErase)) {
error("erase failed");
}
bgnErase = endErase + 1;
}
// Start a multiple block write.
if (!sd.card()->writeStart(bgnBlock, FILE_BLOCK_COUNT)) {
error("writeBegin failed");
}
// Initialize queues.
emptyHead = emptyTail = 0;
fullHead = fullTail = 0;
// Use SdFat buffer for one block.
emptyQueue[emptyHead] = (block_t*)cache;
emptyHead = queueNext(emptyHead);
// Put rest of buffers in the empty queue.
for (uint8_t i = 0; i < BUFFER_BLOCK_COUNT; i++) {
emptyQueue[emptyHead] = &block[i];
emptyHead = queueNext(emptyHead);
}
// Wait for Serial Idle.
Serial.flush();
delay(10);
uint32_t bn = 0;
uint32_t t0 = millis();
uint32_t t1 = t0;
uint32_t overrun = 0;
uint32_t overrunTotal = 0;
uint32_t count = 0;
uint32_t maxlatency = 0;
int32_t diff;
// Start at a multiple of interval.
uint32_t logTime = micros()/LOG_INTERVAL_USEC + 1;
logTime *= LOG_INTERVAL_USEC;
bool closeFile = false;
while (1) {
// Time for next data record.
logTime += LOG_INTERVAL_USEC;
if (Serial.available()) {
closeFile = true;
}
if (closeFile) {
if (curBlock != 0 && curBlock->count >= 0) {
// Put buffer in full queue.
fullQueue[fullHead] = curBlock;
fullHead = queueNext(fullHead);
curBlock = 0;
}
} else {
if (curBlock == 0 && emptyTail != emptyHead) {
curBlock = emptyQueue[emptyTail];
emptyTail = queueNext(emptyTail);
curBlock->count = 0;
curBlock->overrun = overrun;
overrun = 0;
}
do {
diff = logTime - micros();
} while(diff > 0);
if (diff < -10) {
error("LOG_INTERVAL_USEC too small");
}
if (curBlock == 0) {
overrun++;
} else {
acquireData(&curBlock->data[curBlock->count++]);
if (curBlock->count == DATA_DIM) {
fullQueue[fullHead] = curBlock;
fullHead = queueNext(fullHead);
curBlock = 0;
}
}
}
if (fullHead == fullTail) {
// Exit loop if done.
if (closeFile) {
break;
}
} else if (!sd.card()->isBusy()) {
// Get address of block to write.
block_t* pBlock = fullQueue[fullTail];
fullTail = queueNext(fullTail);
// Write block to SD.
uint32_t usec = micros();
if (!sd.card()->writeData((uint8_t*)pBlock)) {
error("write data failed");
}
usec = micros() - usec;
t1 = millis();
if (usec > maxlatency) {
maxlatency = usec;
}
count += pBlock->count;
// Add overruns and possibly light LED.
if (pBlock->overrun) {
overrunTotal += pBlock->overrun;
if (ERROR_LED_PIN >= 0) {
digitalWrite(ERROR_LED_PIN, HIGH);
}
}
// Move block to empty queue.
emptyQueue[emptyHead] = pBlock;
emptyHead = queueNext(emptyHead);
bn++;
if (bn == FILE_BLOCK_COUNT) {
// File full so stop
break;
}
}
}
if (!sd.card()->writeStop()) {
error("writeStop failed");
}
do{
if(digitalRead(switchPin)==LOW){
if(millis()>timeout){ // switchPin is low and has been low for 100ms
truncate = true; // close the file,
// truncate at current record number,
// rename to 'binname'
}
}
else { // switchPin High, not pressed
timeout = millis() + 100; // time that switch has to be pressed to be valid
}
}while(truncate=false);
if(truncate == true){
// Truncate file if recording stopped early.
if (bn != FILE_BLOCK_COUNT) {
//Serial.println(F("Truncating file"));
if (!binFile.truncate(512L * bn)) {
error("Can't truncate file");
}
}
}
binFile.close();
if (!binFile.rename(sd.vwd(), binName)) {
error("Can't rename file");
}
}
//------------------------------------------------------------------------------
void setup(void) {
if (ERROR_LED_PIN >= 0) {
pinMode(ERROR_LED_PIN, OUTPUT);
}
Serial.begin(38400);
sd.begin(38400);
while (!Serial) {}
pinMode(switchPin,INPUT_PULLUP);
Serial.print(F("FreeRam: "));
Serial.println(FreeRam());
Serial.print(F("Records/block: "));
Serial.println(DATA_DIM);
if (sizeof(block_t) != 512) {
error("Invalid block size");
}
setupData();
// initialize file system.
if (!sd.begin(SD_CS_PIN, SPI_FULL_SPEED)) {
sd.initErrorPrint();
fatalBlink();
}
}
//------------------------------------------------------------------------------
void loop(void) {
logData();
binaryToCsv();
}
You need to modify the following code segment:
if (Serial.available()) {
closeFile = true;
}
To be something like:
if (Serial.available() || (stopSwitch(haltPIN) == LOW)) {
closeFile = true;
}
Where stopSwitch is normally HIGH connected to haltPIN
This game has 4 leds and 4 buttons. the game is turning RANDOMLY those leds ON and OFF.
The player should be able to push the right button whenever he sees one led to be turned ON.
The leds should be turning ON and OFF with incerasing speed, so reaction time of a player is shorter and shorter
I have this code but i just know how to add more leds and buttons.
const int BUTTON1 = A0;
const int BUTTON2 = A1;
const int BUTTON3 = A2;
const int BUTTON4 = A3;
int LED1 = 2;
int LED2 = 3;
int LED3 = 4;
int LED4 = 5;
int ran;
int right = 0;
int ledOrder[9];
int guessOrder[9];
void setup()
{
Serial.begin(9600);
pinMode(LED1,OUTPUT);
pinMode(LED2,OUTPUT);
pinMode(LED3,OUTPUT);
pinMode(LED4,OUTPUT);
pinMode(BUTTON1,INPUT);
pinMode(BUTTON2,INPUT);
pinMode(BUTTON3,INPUT);
pinMode(BUTTON4,INPUT);
}
void randomLed() {
for (int i = 0; i < 9; i++) {
ran = random(1,20);
if (ran < 11) {
digitalWrite(LED1,HIGH);
delay(500);
digitalWrite(LED1,LOW);
ledOrder[i] = 1;
}
else {
digitalWrite(LED2,HIGH);
delay(500);
digitalWrite(LED2,LOW);
ledOrder[i] = 2;
}
delay(500);
}
}
void btnClick() {
int ans = 0;
while (ans < 9) {
if (digitalRead(BUTTON1) == HIGH) {
guessOrder[ans] = 1;
ans++;
while (digitalRead(BUTTON1) == HIGH) {
}
}
else if (digitalRead(BUTTON2) == HIGH) {
guessOrder[ans] = 2;
ans++;
while (digitalRead(BUTTON2) == HIGH) {
}
}
}
}
void loop() {
Serial.print("Press button1 to start \n");
while (digitalRead(BUTTON1) == LOW) {
}
randomLed();
btnClick();
for (int i = 0; i < 9; i = i + 1) {
Serial.print("Guess: ");
Serial.print(guessOrder[i]);
Serial.print(" Answer: ");
Serial.print(ledOrder[i]);
if (guessOrder[i] == ledOrder[i]) {
Serial.print(" Right");
right++;
} else {
Serial.print(" Wrong");
}
Serial.print("\n ");
}
Serial.print(right);
Serial.print("/9\n");
delay(2000);
}
If I understand your question correctly, you would like to increase the led blink rate(when the LED's come on) each time the user gets the previous game right. If this is true you should try to put loop in for/if the user got the the previous one(game) right it will increase blink rate by a simple increment( I++;). Comment if you feel this is clarified enough or if your asking for something else