how to create condition using ros odom pose data? - c

I have a mobile autonomous robot that moves using Ros. My goal is to communicate with rosserial via arduino and subscribe to the odom topic. I would like to put some conditions on the exposure data I received after I became a member of Odom. In order to be able to perform some operations at certain points in the coordinates on my map. with a simple example
if (pose_x>2.17 &&pose_x<4.00 &&pose_y<7.6 &&pose_y>9.5 ){
digitalWrite(led_pin, HIGH - digitalRead(13));
}
I want to add conditions like but I don't know how to do that. I'm not very good at software.Below is the code I am trying to do with arduino. I may have been a little silly. I'm still very lacking. I will be grateful for all your help.
#include <ros.h>
#include <std_msgs/String.h>
#include <nav_msgs/Odometry.h>
#include <geometry_msgs/Twist.h>
#include <tf/transform_broadcaster.h>
#include <tf/tf.h>
ros::NodeHandle nh;
ros::Time current_time;
float TIME;
float pose_x, pose_y, angle_z;
geometry_msgs::Quaternion odom_quat;
tf::TransformBroadcaster odom_broadcaster;
std_msgs::String message;
ros::Publisher server_pub("/server_messages", &message);
const int button1_pin = 6;
const int button2_pin = 7;
const int led_pin = 13;
char button1[13] = "2";
char button2[13] = "3";
bool last_reading1;
long last_debounce_time1 = 0;
bool last_reading2;
long last_debounce_time2 = 0;
long debounce_delay = 50;
bool published1 = true;
bool published2 = true;
void odomCallback(const nav_msgs::Odometry & msg) {
nav_msgs::Odometry odom;
odom.header.stamp = current_time;
geometry_msgs::TransformStamped odom_trans;
odom_trans.header.stamp = current_time;
odom_trans.transform.translation.x = pose_x;
odom_trans.transform.translation.y = pose_y;
odom_trans.transform.translation.z = 0.0;
odom_trans.transform.rotation = odom_quat;
odom.pose.pose.position.x = pose_x;
odom.pose.pose.position.y = pose_y;
odom.pose.pose.position.z = 0.0;
odom.pose.pose.orientation = odom_quat;
if (pose_x>-8 && pose_x<10 && pose_y>-8 && pose_y<8) {
digitalWrite(led_pin, HIGH - digitalRead(13));
}
else {
digitalWrite(led_pin, LOW - digitalRead(13));
}
}
ros::Subscriber <nav_msgs::Odometry> sub("/odom", odomCallback);
void setup()
{
nh.initNode();
nh.advertise(server_pub);
nh.subscribe(sub);
//initialize an LED output pin
//and a input pin for our push button
pinMode(led_pin, OUTPUT);
pinMode(button1_pin, INPUT);
pinMode(button2_pin, INPUT);
//Enable the pullup resistor on the button
digitalWrite(button1_pin, HIGH);
digitalWrite(button2_pin, HIGH);
//The button is a normally button
last_reading1 = ! digitalRead(button1_pin);
last_reading2 = ! digitalRead(button2_pin);
}
void loop()
{
bool reading1 = ! digitalRead(button1_pin);
bool reading2 = ! digitalRead(button2_pin);
if (last_reading1 != reading1) {
last_debounce_time1 = millis();
published1 = false;
}
if (last_reading2 != reading2) {
last_debounce_time2 = millis();
published2 = false;
}
//if the button value has not changed for the debounce delay, we know its stable
if ( !published1 == 1 && (millis() - last_debounce_time1) > debounce_delay) {
digitalWrite(led_pin, reading1);
message.data = button1 ;
server_pub.publish(&message);
published1 = true;
}
if ( !published2 == 1 && (millis() - last_debounce_time2) > debounce_delay) {
digitalWrite(led_pin, reading2);
message.data = button2 ;
server_pub.publish(&message);
published2 = true;
}
last_reading1 = reading1;
last_reading2 = reading2;
nh.spinOnce();
}

It seems like you're not using the data from the odomCallback at all.
Looks like pose_x and pose_y values never get set. Try adding this to the beginning of the odomCallback function (not tested):
// set pose_x and pose_y to their most recent values
pose_x = msg.pose.pose.position.x;
pose_y = msg.pose.pose.position.y;

Related

Timer not stopping at Zero D1 mini

Im currently trying to code a timer on a D1 mini that has three tactile switches and will display on a 64x48 OLED display, switch 1 and 2 will increase and decrease the time and 3 will start the time you have put in.
As of now when as it turns on the timer is in a stopped state and you can set your desired time input with switch 1 and 2 and then start the timer with switch 3 but when the timer counts down I want it to stop at 00:00 for you to then input a new time with switch 1 and 2 and then start it again with switch 3. The timer keeps going and does not appear to stop at 00:00.
Here is the code:
#include <Wire.h>
#include <Adafruit_SSD1306.h>
// SCL GPIO5
// SDA GPIO4
#define OLED_RESET 0 // GPIO0
Adafruit_SSD1306 display(OLED_RESET);
int switch1 = D3;
int switch2 = D4;
int switch3 = D5;
int minutes = 0;
int seconds = 0;
int originalMinutesValue = 0;
int originalSecondsValue = 0;
bool timerRunning = false;
bool isReset = false;
void setup() {
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
display.display();
delay(2000);
display.clearDisplay();
display.setTextSize(2);
display.setTextColor(WHITE);
display.setCursor(4,16);
pinMode(switch1, INPUT);
pinMode(switch2, INPUT);
pinMode(switch3, INPUT);
originalMinutesValue = minutes;
originalSecondsValue = seconds;
}
void loop() {
if(digitalRead(switch1) == LOW) {
if(seconds == 0) {
if(minutes > 0) {
minutes--;
seconds = 59;
}
} else {
seconds--;
}
delay(200);
}
if(digitalRead(switch2) == LOW) {
if(seconds == 59) {
minutes++;
seconds = 0;
} else {
seconds++;
}
delay(200);
}
if(digitalRead(switch3) == LOW) {
timerRunning = !timerRunning;
if(timerRunning && !isReset) {
isReset = true;
}
delay(200);
}
if(timerRunning){
if(seconds==0){
if(minutes>0){
minutes--;
seconds=59;
}else{
if(isReset){
minutes = originalMinutesValue;
seconds = originalSecondsValue;
isReset = false;
}else {
timerRunning = false;
}
}
}else{
seconds--;
}
delay(1000);
}
display.clearDisplay();
display.setCursor(4,16);
if(minutes < 10) {
display.print("0");
}
display.print(minutes);
display.print(":");
if(seconds < 10) {
display.print("0");
}
display.print(seconds);
display.display();
}
I have tried a lot of different workarounds but cannot get it to work. Please let me know if you might know the problem.

RPi 4 GPIO Interrupt on Rising and Falling trigger not working in C

Beginner here learning to code linux kernel modules.
I want to write a kernel module for my RPi 4 in C language.
I want to use interrupts to light on a LED when I push a button. As long as the button is pushed, the LED is on and when I release it, the LED is supposed to turn off.
I use the function request_irq() so that my function handling the interrupt is called on the rising edge and on the falling edge of my button by indicating "IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING". I formerly used the function gpio_to_irq(BUTTON_PIN).
request_irq(button_irq, button_ih, IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, "button_irq", NULL);
The function is called when I push the button but not when I release it. It is coded as seen below :
static irqreturn_t button_ih(int irq, void *data)
{
int state;
state = gpio_get_value(BUTTON_PIN);
printk(KERN_INFO "Actual state of the button : %d", state);
//Debounce condition
if(jiffies - last_interrupt_time > msecs_to_jiffies(200))
{
if(state)
{
gpio_set_value(LED_PIN, 1);
}else
{
gpio_set_value(LED_PIN, 0);
}
}
last_interrupt_time = jiffies;
return IRQ_HANDLED;
}
I check whether the value of the button is 1 (pressed) or 0 (released) and want to turn on/off the LED accordingly.
When I try different GPIOs, sometimes, the value of my button is 1 even though I haven't pushed it yet(by printing a message from the init function) and sometimes it's 0. So I don't understand if I'm doing something wrong. I don't think the GPIOs are already used cause I can request them with the function gpio_request_one().
So when the button already has the value 1, the LED turn on but won't switch off when I release the button.
And when the value is already 0, the button value doesn't change to become 1 when I enter the interrupt handler function (and the LED obviously doesn't turn on).
Could you tell me what's wrong with it please?
Form simple C program, not kernel module
This minimal to see how I'm doing.
main.h
typedef struct s_Data {
int exitFlag;
struct {int value; int bcmPin;} In01; //<--- Stock actual GPIO Value
struct {int value; int bcmPin;} In02;
....
struct {int value; int bcmPin;} Out01;
struct {int value; int bcmPin;} Out02;
....
} t_Data;
#define NO_Click 0
#define SimpleClick 1
#define LongClick 2
#define MultiClick 3
typedef struct s_Button {
pthread_t button_thread;
int *exitFlag;
int * input; //Button
int * output;
int old_state;
int new_state;
struct timeval t0;
struct timeval t1;
struct timeval pressedTime;
struct timeval releasedTime;
int clickType;
//float debounce = 0.020; // ms debounce period to prevent flickering when pressing or releasing the button
// debounce not necessary while thread have time to take a coffee
float DCgap; // max ms between clicks for a double click event
float holdTime; // ms hold period: how long to wait for press+hold event
} t_Button;
main.c
#include "main.h"
#include <wiringPi.h>
#include <pthread.h>
// initial state
static t_Data data = {
.exitFlag = 0,
.In01.value = 0, .In01.bcmPin = 4,
.In02.value = 0, .In02.bcmPin = 17,
.Out01.value = 0, .Out01.bcmPin = 4,
.Out02.value = 0, .Out02.bcmPin = 17,
}
static _Data data_prev;
static void *inputRead_threadFn(void *p_Data) {
pinMode(Data.In01.bcmPin, INPUT);
pullUpDnControl(Data.In01.bcmPin, PUD_UP);
pinMode(Data.In02.bcmPin, INPUT);
pullUpDnControl(Data.In02.bcmPin, PUD_UP);
while (!Data.exitFlag) {
Data.In01.value = !digitalRead(Data.In01.bcmPin);
Data.In02.value = !digitalRead(Data.In02.bcmPin);
if (Data.In01.value != Data_old.In01.value) {
Data_old.In01.value = Data.In01.value;
}
if (Data.In02.value != Data_old.In02.value) {
Data_old.In02.value = Data.In02.value;
}
usleep(50)
}
}
static void *outputWrite_threadFn(void *p_Data) {
pinMode(Data.In01.bcmPin, OUTPUT);
pinMode(Data.In02.bcmPin, OUTPUT);
while (!Data.exitFlag) {
digitalWrite(Data.Out01.bcmPin, !Data.Out01.value);
digitalWrite(Data.Out02.bcmPin, !Data.Out02.value);
}
usleep(50)
}
static void *button_threadFn(void *p_Data) {
t_Button *button = (t_Button *)p_data;
LOG("Button[%s] thread initialized\r\n", button->name);
button->old_state = 0;
button->new_state = 0;
button->clickType = NO_Click;
int clickCount = 0;
while(*(button->exitFlag) == 0) {
button->new_state = *(button->input) || *(button->web_input); //*((int *)
if( button->old_state == 0 && button->new_state == 1 ) {
//printf("front montant\r\n"); fflush(stdout);
// *****************************
// traitement sur front montant
// rising edge
// *****************************
button->old_state = 1;
gettimeofday(&button->pressedTime, 0);
//Button pressed
} else if( (button->old_state == 1) && (button->new_state == 0) ) {
//printf("front descendant\r\n"); fflush(stdout);
// *****************************
// traitement sur front descendant
// falling edge
// *****************************
button->old_state = 0;
gettimeofday(&button->releasedTime, 0);
if (my_timedifference_msec(button->releasedTime, button->pressedTime ) < button->DCgap) {
clickCount++;
button->clickType = MultiClick;
}
//Button released
} else if( (button->old_state == 0) && (button->new_state == 0) ) {
// printf("front bas\r\n"); fflush(stdout);
// *****************************
// pas de changement d'état : front bas
// no state change : edge down
// *****************************
gettimeofday(&button->t0, 0);
*(button->output) = 0; //<--- here in your case
//Attendre DC_Gap pour connaitre le nombre de click
// Wait for DC_Gap to know click count
if (my_timedifference_msec(button->t0, button->releasedTime) > button->DCgap) {
if (clickCount == 1) {
LOG("SimpleClick");
//Simple Click
} else if ( clickCount > 1 ) {
//Multiclicks
}
button->clickType = NO_Click;
clickCount = 0;
}
} else if( (button->old_state == 1) && (button->new_state == 1) ) {
// printf("front haut\r\n"); fflush(stdout);
// *****************************
// pas de changement d'état : front haut
// no state change : edge up
// *****************************
gettimeofday(&button->t1, 0);
*(button->output) = 1; //<--- here in your case
//long click
if (my_timedifference_msec(button->t1, button->pressedTime) >= button->holdTime) {
LOG("LongClick");
button->clickType = LongClick;
//do what you want while not released
usleep(30*1000);
}
}
usleep(100);
}
printf("Light Loop::exiting...\r\n"); fflush(stdout);
}
int main(int argc, char** argv) {
wiringPiSetup();
wiringPiSetupGpio();
data_prev = data;
//start input thread
//start output thread
int DCGap = 250; //ms
int HoldTime = 600;
t_Button Buttons[] = {
{ //WC
.exitFlag = &Data.exitFlag,
.DCgap = DCGap,
.holdTime = HoldTime,
.input = &Data.In01.value,
.output = &Data.Out01.value,
},
{ //chambre
.exitFlag = &Data.exitFlag,
.DCgap = DCGap,
.holdTime = HoldTime,
.input = &Data.In02.value,
.output= &Data.Out02.value,
}
}
//start buttons threads
for (i = 0; i < (sizeof(Buttons) / sizeof(t_Button)) ; i++) {
ret = pthread_create (&Buttons[i].button_threadFn, NULL, fn_Button, &Buttons[i]);
if (ret) {
fprintf (stderr, "%s", strerror (ret));
}
}
//threads join
return (EXIT_SUCCESS);
}
Ok so thanks for all the comments/answers.
It was indeed because I wasn't using any pull-up or pull-down resistor properly.
So I changed my circuit as following:
Circuit

barcode reader for Arduino recognize char

I have a barcode code but need it to recognize the barcode so it can print to serial monitor. I have searched that I need to have it convert to int from char but have yet to find a way to do that if that is the answer.
For example I scan a barcode and if it is a certain number, then the serial monitor will print it.
#include <hid.h>
#include <hiduniversal.h>
#include <usbhub.h>
#include <Usb.h>
#include <hidboot.h>
#include <avr/pgmspace.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <Bridge.h>
#include <FileIO.h>
#include <TM1637Display.h>
#define DEBUG true
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);
const byte BarcodeLength = 11;
const int buzzer = 2;
const int CLK = 9; //Set the CLK pin connection to the display
const int DIO = 8; //Set the DIO pin connection to the display
const int DIO2 = 7; // Set 2nd DIO pin to second connection to display
const int CLK2 = 6; // Set the 2nd CLK pin to the second connection to display.
const int procTime = 5; // this is the time it takes for the process to finish countdown
int NumStep = 0; //Variable to interate
TM1637Display countdownDisplay(CLK, DIO); //set up the 4-Digit Display.
TM1637Display DelayedDisplay(CLK2, DIO2); //set up the 4-Digit Display.
class BarcodeReader : public KeyboardReportParser
{
USB Usb;
USBHub Hub;
HIDUniversal Hid;
HIDBoot<HID_PROTOCOL_KEYBOARD> Keyboard;
uint8_t buffer[15];
byte length;
bool valid;
void addCharacter(uint8_t c);
public:
BarcodeReader();
void begin();
void task();
const uint8_t* barcode();
void reset();
protected:
virtual void OnKeyDown(uint8_t mod, uint8_t key);
};
BarcodeReader::BarcodeReader()
: Usb()
, Hub(&Usb)
, Hid(&Usb)
, Keyboard(&Usb)
, length(0)
, valid(false)
{
}
void BarcodeReader::begin()
{
if (Usb.Init() == -1) {
Serial.println("OSC did not start.");
}
else
Serial.println("Barcode Ready");
Hid.SetReportParser(1, this);
}
void BarcodeReader::task()
{
Usb.Task();
}
void BarcodeReader::addCharacter(uint8_t c)
{
if (valid) {
// already have a barcode, new one will overwrite it
reset();
}
// could check for \n or \r if necessary, or even implement a timing
// mechanism for detecting end of barcode input, but for now we just
// assume fixed width field with no output separators
buffer[length++] = c;
//buffer[length] = '\0';
if (buffer[length] == '\0')
{
valid = true;
}
};
// return value no longer valid after another call to task()
const uint8_t* BarcodeReader::barcode()
{
return (valid) ? buffer : 0;
}
void BarcodeReader::reset()
{
length = 0;
valid = false;
}
void BarcodeReader::OnKeyDown(uint8_t mod, uint8_t key) {
uint8_t c = OemToAscii(mod, key);
if (c) addCharacter(c);
}
BarcodeReader barcodeReader;
void setup() {
countdownDisplay.showNumberDec(0);
DelayedDisplay.showNumberDec(0);
Bridge.begin();
Console.begin();
FileSystem.begin();
Serial.begin(9600);
if (DEBUG) Console.println("Done setup");
lcd.begin(16, 2);
pinMode(buzzer,OUTPUT);
//Serial.begin(115200);
lcd.print("Please Scan Your ID: ");
barcodeReader.begin();
countdownDisplay.setBrightness(0x0a); //set the diplay to maximum brightness
DelayedDisplay.setBrightness(0x0a);
}
void loop() {
//char *goodCards = { "1234567" };
//String dataString = "Testing, 1, 2, 3...";
File dataFile = FileSystem.open("/mnt/sda1/datalog.txt", FILE_APPEND);
// If the file opens successfully, write the string to it, close the file,
// and print the information to the Serial monitor.
barcodeReader.task();
const char* barcode = barcodeReader.barcode();
if (barcode || dataFile) {
lcd.print(barcode);
dataFile.print(barcode);
Serial.print(barcode);
barcodeReader.reset();
dataFile.close();
//If the barcode is the word 'Setup' then print setup to the screen
//search array of char conver strcmp(). You are sending 0101 not the actual value of 1234567
// collect all the input, convert it to an int
if(barcode == "0001") {
{
Serial.println(": SETUP");
}
}
}
//timer and barcode
//
// if(barcode == "1234567") {
// Serial.print(barcode);
// Serial.println(": SETUP");
//
//// analogWrite(A1,0);
//// analogWrite(A2,0);
// }
// if(barcode == "KAYAMAD") {
// Serial.print(barcode);
// Serial.println(": RUN");
//
//// analogWrite(A0,0);
//// analogWrite(A2,0);
// countdownDisplay.showNumberDec(0);
// DelayedDisplay.showNumberDec(0);
// for(int NumStep = procTime; NumStep > 0 ; NumStep--) //Interrate NumStep
// {
// countdownDisplay.showNumberDec(NumStep); //Display the Variable value;
// //DelayedDisplay.showNumberDec(NumStep); //Display the Variable value;
// delay(1000); //A second delay between steps.
// }
//
// for (int NumStep = 0; NumStep < 5 ; NumStep++) //Interrate NumStep
// {
// //countdownDisplay.showNumberDec(NumStep); //Display the Variable value;
// DelayedDisplay.showNumberDec(NumStep); //Display the Variable value;
// countdownDisplay.showNumberDec(0);
// delay(1000); //A second delay between steps.
//
// }
//
// }
//
// else if (barcode == "2234663") {
// Serial.print(barcode);
// Serial.println(": DELAY");
//
//// analogWrite(A0,0);
//// analogWrite(A1,0);
// countdownDisplay.showNumberDec(0);
// DelayedDisplay.showNumberDec(0);
//
//
// for (int NumStep = 0; NumStep < 5 ; NumStep++) //Interrate NumStep
// {
// //countdownDisplay.showNumberDec(NumStep); //Display the Variable value;
// DelayedDisplay.showNumberDec(NumStep); //Display the Variable value;
// countdownDisplay.showNumberDec(0);
// delay(1000); //A second delay between steps.
//
// }
//
//
// }
//
// If there is a problem opening the file, send an error to the Serial monitor
else {
if (DEBUG) Console.println("Error opening datalog.txt");
}
}
"Number" you get Computer sees as text, not number. We are sure that barcode will always be number. Conver char to int with atoi function.
Here's an example:
const char *bar = "123";
int bc = atoi(bar);

How to detect how long a button was pressed in Arduino?

How can I detect how long a button was pressed / released in Arduino and then print some custom output after that?
Arduino can only detect the state of your button (pressed OR unpressed).
You could use a timer variable (based on this example from their docs) to save the exact time when you pressed or released the button, so you can check the difference between both variables to calculate how long it is on hold or idle.
The code could look like this:
const int buttonPin = 2;
int buttonState = 0; // current state of the button
int lastButtonState = 0; // previous state of the button
int startPressed = 0; // the moment the button was pressed
int endPressed = 0; // the moment the button was released
int holdTime = 0; // how long the button was hold
int idleTime = 0; // how long the button was idle
void setup() {
pinMode(buttonPin, INPUT); // initialize the button pin as a input
Serial.begin(9600); // initialize serial communication
}
void loop() {
buttonState = digitalRead(buttonPin); // read the button input
if (buttonState != lastButtonState) { // button state changed
updateState();
}
lastButtonState = buttonState; // save state for next loop
}
void updateState() {
// the button has been just pressed
if (buttonState == HIGH) {
startPressed = millis();
idleTime = startPressed - endPressed;
if (idleTime >= 500 && idleTime < 1000) {
Serial.println("Button was idle for half a second");
}
if (idleTime >= 1000) {
Serial.println("Button was idle for one second or more");
}
// the button has been just released
} else {
endPressed = millis();
holdTime = endPressed - startPressed;
if (holdTime >= 500 && holdTime < 1000) {
Serial.println("Button was held for half a second");
}
if (holdTime >= 1000) {
Serial.println("Button was held for one second or more");
}
}
}
However, if you want to trigger an event while the button is still pressed (or maybe you want to increment a counter in some display), you can still do the same math.
Change your condition in the loop function to be like this:
if (buttonState != lastButtonState) {
updateState(); // button state changed. It runs only once.
} else {
updateCounter(); // button state not changed. It runs in a loop.
}
And then implement your new function like this:
void updateCounter() {
// the button is still pressed
if (buttonState == HIGH) {
holdTime = millis() - startPressed;
if (holdTime >= 1000) {
Serial.println("Button is held for more than a second");
}
// the button is still released
} else {
idleTime = millis() - endPressed;
if (idleTime >= 1000) {
Serial.println("Button is released for more than a second");
}
}
}
for your interest here's an example of code using 2 arrays to store button states of arduino pin given to the corresponding input button. During the loop you can do a simple check with the wanted repeat:
if(button_down(But1_pin, BTN_LOOP_DELAY_MS))
{
// code here repeated if the button is either clicked or maintained
}
button_down() also defers the first repeat by DELAY_WAIT_BEFORE_REPEAT ms.
Here the full tested example:
#define BTN_LOOP_DELAY_MS 100
#define DELAY_WAIT_BEFORE_REPEAT 500
#define NB_MAX_PIN_INPUT 13
#define But1_pin 7
#define But2_pin 6
// array to check status change
bool prev_button[NB_MAX_PIN_INPUT];
unsigned long button_last_down[NB_MAX_PIN_INPUT];
// macro : our read init with prev_button storage
#define READ_INIT_BUTTON(pin) \
do{ \
pinMode(pin, INPUT); \
prev_button[pin] = digitalRead(pin); \
} while(false)
// function at the end of the code
bool button_down(byte pin_num, unsigned int delay_repeated);
void setup() {
READ_INIT_BUTTON(But1_pin);
READ_INIT_BUTTON(But2_pin);
Serial.begin(115200);
}
void loop() {
if(button_down(But1_pin, BTN_LOOP_DELAY_MS))
{
Serial.print("new inpulse");
Serial.print(millis());
Serial.println();
}
if(button_down(But2_pin, BTN_LOOP_DELAY_MS))
{
Serial.println("button2");
}
}
bool button_down(byte pin_num, unsigned int delay_repeated)
{
bool b = digitalRead(pin_num);
bool r = false;
unsigned long currentMillis = millis();
if(prev_button[pin_num] != HIGH && b == HIGH)
{
r = true;
button_last_down[pin_num] = currentMillis + DELAY_WAIT_BEFORE_REPEAT;
}
else if(b == HIGH
&& prev_button[pin_num] == HIGH
&& currentMillis > button_last_down[pin_num]
&& currentMillis - button_last_down[pin_num] > delay_repeated
)
{
// save the last time we give a button impusle at true
button_last_down[pin_num] = currentMillis;
r = true;
}
// store button state, if changed
if(prev_button[pin_num] != b)
{
prev_button[pin_num] = b;
}
return r;
}
This following steps works:
If the button state satisfies.
Then read the millis() values one time(Using flag) and find the
duration by comparing with current millis() value.
void buttonLongPress() {
uint32_t duration = 0;
if (digitalRead(button_pin) == LOW) {
if (pressReadLimit == 0) {
pressTime = millis();
pressReadLimit = 1;
}
duration = millis() - pressTime;
if (duration >= 3000) {
Serial.println("Long press");
}
Serial.println(duration);
} else {
duration = 0;
pressReadLimit = 0;
}
}
Serial monitor result

How to use callback function in processing?

How do i call my array after a certain amount of time so it creates an object at certain intervals. I want my array to create a sphere every 3 seconds.
Ball [] ball;
void setup()
{
size(600,600,P3D);
ball = new Ball[3];
ball[0] = new Ball();
ball[1] = new Ball();
ball[2] = new Ball();
}
void draw()
{
background(255);
for (int i = 0; i < ball.length; i++) {
ball[i].drawBall();
}
}
class Ball
{
float sphereSize = random(30, 90);
float sphereX = random(-2200, 2800);
float sphereY = 0;
float sphereZ = random(-2200, 2800);
void drawBall()
{
translate(sphereX, sphereY, sphereZ);
sphere(sphereSize);
sphereY +=1;
}
}
Easiest way is to store the time in a variable using a time keeping function like millis().
The idea is simple:
store a previous time and a delay amount
keep track of time continuously
if the current time is greather than the previously stored time and the delay, then that delay interval has passed.
Here's a simple sketch to illustrate the idea:
int now,delay = 1000;
void setup(){
now = millis();
}
void draw(){
if(millis() >= (now+delay)){//if the interval passed
//do something cool here
println((int)(frameCount/frameRate)%2==1 ? "tick":"tock");
background((int)(frameCount/frameRate)%2==1 ? 0 : 255);
//finally update the previously store time
now = millis();
}
}
and integrated with your code:
int ballsAdded = 0;
int ballsTotal = 10;
Ball [] ball;
int now,delay = 1500;
void setup()
{
size(600,600,P3D);sphereDetail(6);noStroke();
ball = new Ball[ballsTotal];
now = millis();
}
void draw()
{
//update based on time
if(millis() >= (now+delay)){//if the current time is greater than the previous time+the delay, the delay has passed, therefore update at that interval
if(ballsAdded < ballsTotal) {
ball[ballsAdded] = new Ball();
ballsAdded++;
println("added new ball: " + ballsAdded +"/"+ballsTotal);
}
now = millis();
}
//render
background(255);
lights();
//quick'n'dirty scene rotation
translate(width * .5, height * .5, -1000);
rotateX(map(mouseY,0,height,-PI,PI));
rotateY(map(mouseX,0,width,PI,-PI));
//finally draw the spheres
for (int i = 0; i < ballsAdded; i++) {
fill(map(i,0,ballsAdded,0,255));//visual cue to sphere's 'age'
ball[i].drawBall();
}
}
class Ball
{
float sphereSize = random(30, 90);
float sphereX = random(-2200, 2800);
float sphereY = 0;
float sphereZ = random(-2200, 2800);
void drawBall()
{
pushMatrix();
translate(sphereX, sphereY, sphereZ);
sphere(sphereSize);
sphereY +=1;
popMatrix();
}
}

Resources