I suggest that Windows programmers who want to catch Ctrl-C should strongly prefer to call SetConsoleCtrlHandler instead
If all you want to do is to terminate a loop with ctrl-c (or any other char) and continue, then you don't need to install a handler. You do something like this:
Thank you so much for the encouragement, for the links provided (for core guidelines, and so on) and for the valuable suggestions offered including the one on using directives.
I plan to revert to these resources as I make progress.
@seeplus:
Wow, I'm speechless! Never knew this was possible : )
Thank you for sharing this.
I would keep you guys posted when other ideas and challenges come to mind while I continue work on this personal project.
What is the OS on your Raspberry Pi, if any? According to Wikipedia it can utilize quite a variety. The default is a *nix variation created for the board, with a zero-price version of Windows 10 IoT Core available for a Pi 2.
Lol! Thanks for the lighthearted response! Apologies for not replying sooner.
I have tried to implement class and client interface for the code. The first version where I have:
1.) CGPIOCleanExit.h (class header with function prototypes and definition)
2.) CGPIOSetup.h (ditto)
3.) gpio_input_intern_toggle_01.cpp (client source code)
This first version above compiled and ran successfully with no errors. (Please see code below:)
// gpio_input_intern_toggle_01.cpp
#include <iostream>
#include <wiringPi.h>
#include <signal.h>
#include "CGPIOCleanExit.h" // Include header files
#include "CGPIOSetup.h"
using std::cout;
using std::cin;
using std::endl;
typedefunsignedlongint ULONG; // typedef defined (See 101.lv)
typedefunsignedshortint USHORT;
typedefvolatile sig_atomic_t VSIGATM; // " (see newbieg (2022),
// cplusplus.com)
// ****************************************** //
// Declare instance of global class object (Recall this is more secure
// than using regular global variable, although still in search for
// alternative that would not involve use of global entities however,
// will support future maintenance of program in future devs.):
CGPIOCleanExit Regular;
// Declare signal handling fxn:
void cKeyboardInterrupt(int signalNum)
{
//CGPIOCleanExit Regular;
Regular.setBlink(1); // Access class member function through object
// and set blinkState, accordingly
}
// Main program begins:
int main(void)
{
signal(SIGINT, cKeyboardInterrupt); // Call signal() fxn to capture
// keyboard interrupt
wiringPiSetup(); // Call wiringPi library and numbering system
//CGPIOCleanExit Regular;
//Regular.setBlink(0);
//cout << Regular.getBlink() << endl;
constint totalPins {2}; // Total number of pins. NOTE:
// without modifier const, that compiler will
// issue an error while trying to initialize
// array in the next line
// CGPIOSetup Pins[2];
CGPIOSetup Pins[totalPins - 1]; // Declare array of size =
// number of elements - 1
Pins[0].setInputPin(29); // Initialize element of array
Pins[1].setInputPin(28); // with appropriate pin number
int pin1 = Pins[0].getInputPin(); // Define and initialize pin
int pin2 = Pins[1].getInputPin(); // with appropriate pin number
pinMode(pin1,INPUT); // Set GPIO pin mode
pinMode(pin2,OUTPUT);
pullUpDnControl(pin1, PUD_UP); // Set GPIO pin to pull-up resistor
// (See wiringpi.com for more details)
// Initialize variable to store measured value:
// NOTE: 'readValue' in previous code has been replaced
// by 'buttonState':
USHORT buttonState = 1, buttonStateOld = 1, LEDState = 0;
// Initialize while loop and call class member function
// which gets blinkState value/condition (which acts as counter)
while(!Regular.getBlink())
{
buttonState = digitalRead(pin1); // Read value from pin specified
cout << buttonState << endl; // Print read value to screen
// If statments:
// Check previous and current state:
if ((buttonState == 1) && (buttonStateOld == 0))
{
if (LEDState == 0) // Recall, relation operators
{
LEDState = 1; // return 1 (true) or 0 (false)
// The next line is another place where the magic happens!:
// See where 'LEDState' from previous line is passed as
// an argument:
digitalWrite(pin2,LEDState); // Turn ON/OFF depending on
// 'LEDState'
}
else
{
LEDState = 0;
digitalWrite(pin2,LEDState);
}
}
buttonStateOld = buttonState; // Update previous state of
// button
delay(100); // sleep for 100ms (0.1 second)
}
return 0;
}
// CGPIOCleanExit.cpp
#include <iostream>
#include <wiringPi.h>
#include <signal.h>
#include "CGPIOCleanExit.h"
using std::cout;
using std::cin;
using std::endl;
typedefunsignedlongint ULONG;
typedefunsignedshortint USHORT;
typedefvolatile sig_atomic_t VSIGATM;
CGPIOCleanExit::CGPIOCleanExit()
{
cout << "CGPIOCleanExit constructor initialized...\n";
m_BlinkState = 0; // To properly initialize class member data
}
// Class destructor declaration:
CGPIOCleanExit::~CGPIOCleanExit()
{
// destruction process no action other than its intended purpose
cout << "CGPIOCleanExit destructor initialized...\n";
}
// Class public methods declaration
bool CGPIOCleanExit::getBlink()
{
return m_BlinkState;
}
void CGPIOCleanExit::setBlink(int b)
{
m_BlinkState = b; // Set m_BlinkState, in this case, '0' reps 'False'
// Clean up and reset wiringPin
cout << "\nCommence clean up process..." << endl;
digitalWrite(29, LOW); // Reset pin to zero (0)
pinMode(28, INPUT); // Reset pin to INPUT (that is, IN)
digitalWrite(28, LOW); // ditto
pinMode(28, INPUT); // ditto
cout << "Clean up process complete!" << endl;
}
// CGPIOSetup.cpp
#include <iostream>
#include <wiringPi.h>
#include <signal.h>
#include "CGPIOSetup.h"
using std::cout;
using std::cin;
using std::endl;
typedefunsignedlongint ULONG;
typedefunsignedshortint USHORT;
typedefvolatile sig_atomic_t VSIGATM;
// Class constructor declaration
// pnval = 29 corresponds to GPIO wiringPi pin #29)
// WARNING: Check GPIO pin is safely connected!
CGPIOSetup::CGPIOSetup(int pnval = 29) // pnval = pinNumber value
{
cout << "CGPIOSetup constructor initialized...\n";
m_PinNumber = pnval; // To properly intialize class member data
}
// Class destructor declaration:
CGPIOSetup::~CGPIOSetup()
{
// destruction process no action other than its intended purpose
cout << "CGPIOSetup destructor initialized...\n";
}
// Class public methods declaration
// getInputPin public accessor fxn defn:
ULONG CGPIOSetup::getInputPin() const
{
return m_PinNumber;
}
// setOutputPin public accessor fxn defn:
void CGPIOSetup::setInputPin(int pinNumber)
{
m_PinNumber = pinNumber; // Initialize with value passed
}
// gpio_input_intern_toggle_01.cpp (ditto...)
However, when I try to compile the code, here is the error message that I get:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
$ g++ -Wall -c gpio_input_intern_toggle_01.cpp -lwiringPi
gpio_input_intern_toggle_01.cpp: In function ‘int main()’:
gpio_input_intern_toggle_01.cpp:73:34: error: no matching function for call to ‘CGPIOSetup::CGPIOSetup()’
73 | CGPIOSetup Pins[totalPins - 1]; // Declare array of size =
| ^
In file included from gpio_input_intern_toggle_01.cpp:27:
CGPIOSetup.h:43:9: note: candidate: ‘CGPIOSetup::CGPIOSetup(int)’
43 | CGPIOSetup(int pnval); // Constructor prototype
| ^~~~~~~~~~
CGPIOSetup.h:43:9: note: candidate expects 1 argument, 0 provided
CGPIOSetup.h:39:7: note: candidate: ‘constexpr CGPIOSetup::CGPIOSetup(const CGPIOSetup&)’
39 | class CGPIOSetup
| ^~~~~~~~~~
CGPIOSetup.h:39:7: note: candidate expects 1 argument, 0 provided
I'm wondering, does it mean I need to write a separate constructor for an array type? I have also been trying to figure this out since last time. Please do you guys have any suggestions? Thank you!
Thank you! Going forward, should I just stick to declaring default value in the function prototype declaration as opposed to the definition?
Please could you also post the link to the documentation so I could read up more on this subject? That way, I might be able to decode the error messages better next time especially since it's suggestion aren't as intuitive as one might think.
Plus, I got another error saying undefined reference
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
$ g++ -Wall -o gpio_input_intern_toggle_01 gpio_input_intern_toggle_01.cpp -lwiringPi
/usr/bin/ld: /tmp/ccMbRMPx.o: in function `cKeyboardInterrupt(int)':
gpio_input_intern_toggle_01.cpp:(.text+0x18): undefined reference to `CGPIOCleanExit::setBlink(int)'
/usr/bin/ld: /tmp/ccMbRMPx.o: in function `main':
gpio_input_intern_toggle_01.cpp:(.text+0x6c): undefined reference to `CGPIOSetup::CGPIOSetup(int)'
/usr/bin/ld: gpio_input_intern_toggle_01.cpp:(.text+0x88): undefined reference to `CGPIOSetup::setInputPin(int)'
/usr/bin/ld: gpio_input_intern_toggle_01.cpp:(.text+0x9c): undefined reference to `CGPIOSetup::setInputPin(int)'
/usr/bin/ld: gpio_input_intern_toggle_01.cpp:(.text+0xa8): undefined reference to `CGPIOSetup::getInputPin() const'
/usr/bin/ld: gpio_input_intern_toggle_01.cpp:(.text+0xc0): undefined reference to `CGPIOSetup::getInputPin() const'
/usr/bin/ld: gpio_input_intern_toggle_01.cpp:(.text+0x10c): undefined reference to `CGPIOCleanExit::getBlink()'
/usr/bin/ld: gpio_input_intern_toggle_01.cpp:(.text+0x1e0): undefined reference to `CGPIOSetup::~CGPIOSetup()'
/usr/bin/ld: gpio_input_intern_toggle_01.cpp:(.text+0x220): undefined reference to `CGPIOSetup::~CGPIOSetup()'
/usr/bin/ld: gpio_input_intern_toggle_01.cpp:(.text+0x248): undefined reference to `CGPIOSetup::~CGPIOSetup()'
/usr/bin/ld: /tmp/ccMbRMPx.o: in function `__static_initialization_and_destruction_0(int, int)':
gpio_input_intern_toggle_01.cpp:(.text+0x2bc): undefined reference to `CGPIOCleanExit::CGPIOCleanExit()'
/usr/bin/ld: gpio_input_intern_toggle_01.cpp:(.text+0x2f0): undefined reference to `CGPIOCleanExit::~CGPIOCleanExit()'
collect2: error: ld returned 1 exit status