cancel
Showing results for 
Search instead for 
Did you mean: 

How to get a state of flex button in TouchGFX?

KDyrb.1
Associate II

Hi,
I am writing here because I need a help.
I want to use flex button this way - when I hold pressed button then virtual function is executed, so when I release button then the virtual function stops.
I try for example .getPressed() in handleTickEvent, but it doesn't working. I try a sample with CustomButton from this forum but I can't use it enough.


Can somebody help me ?

I will be very grateful for help.

Best regards,
Kamil

13 REPLIES 13
JTP1
Lead

Hello

Have you make sure your handleTickEvent is working and called every tick ? 

If your button is located to customContainer, check this 

https://community.st.com/t5/stm32-mcus-touchgfx-and-gui/handletickevent-not-working-with-container/m-p/263835#M20364

 

Here is also example how to use getPressed in handleTick:

https://community.st.com/t5/stm32-mcus-touchgfx-and-gui/how-do-i-trigger-a-new-virtual-function-when-a-touch-button/m-p/52581#M100

 

Hope these helps you. If not, maybe show us your code which is not working.

Br JTP

tdecker2
Associate III

Make sure your virtual function is non-blocking. From your description it seems like you have a while-loop or similar checking for the release of the FlexButton. But TouchGFX will freeze when the called function is blocking.

I use handleTickEvent in MainView - not in ButtonContainer.
Here a code of my handleTickEvent in MainView:

 

void MainView::handleTickEvent() { if(zliczoneFlaga == 1) { dlugosc_materialu_View = dlugosc_ustawiona2; } Unicode::snprintfFloat(textArea_dlugosc_ustawionaBuffer, TEXTAREA_DLUGOSC_USTAWIONA_SIZE, "%0.1f", dlugosc_ustawiona2 ); textArea_dlugosc_ustawiona.invalidate(); WysylamBigosFloat(dlugosc_materialu_View); boxProgress1.setValue(dlugosc_materialu_View); boxProgress1.invalidate(); Unicode::snprintfFloat(textArea_dlugosc_materialuBuffer, TEXTAREA_DLUGOSC_MATERIALU_SIZE, "%0.1f", dlugosc_materialu_View ); textArea_dlugosc_materialu.invalidate(); boxProgress1.setRange(0, dlugosc_ustawiona2); boxProgress1.invalidate(); if((dlugosc_ustawiona2 - dlugosc_materialu_View) <= 0.01) { scalableImage_start.setVisible (true); scalableImage_start.invalidate(); scalableImage_start_1.setVisible (false); scalableImage_start_1.invalidate(); } if(flexButtonCofnij.getPressed() == 1) { HAL_GPIO_WritePin(GPIOB, P2_Pin, GPIO_PIN_SET); } else { HAL_GPIO_WritePin(GPIOB, P2_Pin, GPIO_PIN_RESET); } }
View more

 

FlexButtonCofnij is use to control P2_Pin output.
In previous post I expressed myself incorrectly because when I hold a button then the P2_pin output change a state all time but I want to that when I hold button then P2_pin is SET, when I release then P2_pin is RESET.

Do you understand evrything?

Thanks for our help!

Hello @KDyrb.1 ,

Based on your last comment, if you want to set or reset a pin, you should handle that function inside Model.cpp to be able to access HAL_GPIO_WritePin() , and you don't want to set or reset the pin every frame.
Instead, follow the comment made by @JTP1 (especially, the second forum thread he mentioned), and call HAL_GPIO_WritePin(GPIOB, P2_Pin, GPIO_PIN_SET) when the button is pressed and call reset when it is released.
Your code should look like below:

void Screen1View::flexButtonClickHandler(const touchgfx::BoxWithBorderButtonStyle< touchgfx::ClickButtonTrigger >& b, const ClickEvent& event) { if (&b == &flexButton1) { if (event.getType() == ClickEvent::PRESSED) { touchgfx_printf("Button is pressed..\n"); //presenter->setPin(); } else if (event.getType() == ClickEvent::RELEASED) { touchgfx_printf("Button is released..\n"); //presenter->resetPin(); } } }

Please refer to Backend Communication to read more about how to call hardware related functions.

I hope this helps you, don't hesitate to ask more questions!

Mohammad MORADI
ST Software Developer | TouchGFX

@Mohammad MORADI ESFAHANIASL 
Thank you for your reply!
I know that I should control hardware in Model.cpp, but I was desperate and I tried evrything - a lot of *** idea.

I checked a way which was suggested by @JTP1 in the morning and i have a problem - I can't add a callback to the constructor:

KDyrb1_0-1722440025691.png


Do you have a idea where is a problem?

I will be very grateful!

Best regards.

// Try like this: MainView::MainView(): flexButtonClickedCallback(this,&MainView::flexButtonClickHandler) { keyboard.setPosition (0,0, 379, 320); add(keyboard); keyboard.setVisible (false); keyboard.invalidate(); //gaugel.setValue(bigos), }

If not work, can you show mainView.hpp and flexButtonClickHandler function  from mainView.cpp

Br JTP

About the backend communication:, maybe example project 'MVP_toggleBtnExV1' in this thread helps you after you have read the documentation.

https://community.st.com/t5/stm32-mcus-products/toggle-button-off-after-a-specific-interval/td-p/568514

 

@JTP1  yours advice with callback is good and I can compile project.
Outputs are turn on/turn off but they are switched all the time when I hold the flexButton - the same effect I had at the beginings, when I wrote here.
Here a code od MainView.hpp:

#ifndef MAIN_VIEW_HPP #define MAIN_VIEW_HPP #include <gui_generated/main_screen/MainViewBase.hpp> #include <gui/main_screen/MainPresenter.hpp> #include <gui/common/CustomKeyboard.hpp> #include <gui/common/customButtonContainer.hpp> class MainView : public MainViewBase { public: MainView(); ~MainView() {}; virtual void setupScreen(); virtual void tearDownScreen(); virtual void exitClicked(); virtual void Dlugosc_ustawionaClicked(); void WysylamBigos(uint16_t value); void WysylamBigosFloat(float value2); void handleTickEvent(); virtual void startClicked(); virtual void stopClicked(); virtual void resetClicked(); void WyslijFlage(); virtual void enter_clicked(); virtual void cofnij_clicked(); void sendToScreen_zliczoneFlaga(int); // Add this public function definition: void flexButtonClickHandler(const touchgfx::TextButtonStyle< touchgfx::ImageButtonStyle< touchgfx::ClickButtonTrigger > > & ,const ClickEvent& e); protected: CustomKeyboard keyboard; int namemod; int agemod; char dataBuf[20]; char agebuf[TEXTAREA_DLUGOSC_USTAWIONA_SIZE]; //int start_flag = 0; touchgfx::CustomButtonContainer customButton; Callback<MainView, const CustomButtonContainer&, bool&> buttonEventCallback; void handleButtonEvent(const CustomButtonContainer& element, bool& buttonState); // And add this protected function definition: Callback<MainView, const touchgfx::TextButtonStyle< touchgfx::ImageButtonStyle< touchgfx::ClickButtonTrigger > > &,const ClickEvent&> flexButtonClickedCallback; private: }; #endif // MAIN_VIEW_HPP
View more

 Here a code od MainView.cpp:

#include <gui/main_screen/MainView.hpp> #include "BitmapDatabase.hpp" #ifndef SIMULATOR #include "stdio.h" #include "main.h" #include <stdlib.h> #endif uint16_t bigos2; float dlugosc_materialu_View; float dlugosc_ustawiona_View; int kurwa = 0; extern "C" { extern __IO int start_flag; extern __IO int nawijanieAktywne_flaga; extern __IO int cofanieAktywne_flaga; extern __IO int ok_flag = 0; extern __IO float dlugosc_ustawiona2; extern __IO int zliczoneFlaga; } MainView::MainView(): flexButtonClickedCallback(this,&MainView::flexButtonClickHandler) { keyboard.setPosition (0,0, 379, 320); add(keyboard); keyboard.setVisible (false); keyboard.invalidate(); //gaugel.setValue(bigos), } void MainView::setupScreen() { MainViewBase::setupScreen(); //customButton.setAction(buttonEventCallback); flexButtonCofnij.setClickAction(flexButtonClickedCallback); } void MainView::tearDownScreen() { MainViewBase::tearDownScreen(); } void MainView::Dlugosc_ustawionaClicked() { keyboard.setVisible (true); keyboard.invalidate(); //flexButtonOK.setVisible(true); //flexButtonOK.invalidate(); //flexButtonEXIT.setVisible(true); //flexButtonEXIT.invalidate(); //scalableImage_enter.setVisible(false); //scalableImage_enter.invalidate(); //image_enter.setVisible(false); //image_enter.invalidate(); //flexButton_ENTER.setVisible(false); //flexButton_ENTER.invalidate(); //scalableImage_settings.setVisible(false); //scalableImage_settings.invalidate(); //image_settings.setVisible(false); //image_settings.invalidate(); flexButton_SETTINGS.setVisible(false); flexButton_SETTINGS.invalidate(); //scalableImage_LOGO.setVisible(false); //scalableImage_LOGO.invalidate(); //image_LOGO.setVisible(false); //image_LOGO.invalidate(); flexButton_LOGO.setVisible(false); flexButton_LOGO.invalidate(); agemod = 1; ok_flag = 1; boxProgress1.setVisible (false);// tutej chce zeby nie było widać progress bar kiedy jest klawiatura aktywna boxProgress1.invalidate(); } void MainView::enter_clicked() { keyboard.setVisible (false); keyboard.invalidate(); //flexButtonEXIT.setVisible(false); //flexButtonEXIT.invalidate(); if(ok_flag == 1) { Unicode::strncpy(textArea_dlugosc_ustawionaBuffer, keyboard.getBuffer(), TEXTAREA_DLUGOSC_USTAWIONA_SIZE); textArea_dlugosc_ustawiona.invalidate(); ok_flag = 0; } keyboard.clearBuffer(); int i = 0; do { agebuf[i] = (char) textArea_dlugosc_ustawionaBuffer[i]; i++; }while(textArea_dlugosc_ustawionaBuffer[i] != 0); sprintf(dataBuf, "%s", agebuf); // DOałem to żęb w ustawionej wyświetlało to samo co w ługości materiału - czyli z kropką. dlugosc_ustawiona_View = atof(agebuf); Unicode::snprintfFloat(textArea_dlugosc_ustawionaBuffer, TEXTAREA_DLUGOSC_USTAWIONA_SIZE, "%0.1f", dlugosc_ustawiona2 ); // dla zmiennoprzecinkowych textArea_dlugosc_ustawiona.invalidate(); presenter->sendData(dataBuf); memset (agebuf, '\0', TEXTAREA_DLUGOSC_USTAWIONA_SIZE); //scalableImage_settings.setVisible(true); //scalableImage_settings.invalidate(); //image_settings.setVisible(true); //image_settings.invalidate(); flexButton_SETTINGS.setVisible(true); flexButton_SETTINGS.invalidate(); //scalableImage_LOGO.setVisible(true); //scalableImage_LOGO.invalidate(); //image_LOGO.setVisible(true); //image_LOGO.invalidate(); flexButton_LOGO.setVisible(true); flexButton_LOGO.invalidate(); boxProgress1.setVisible (true);// tutej chce zeby nie było widać progress bar kiedy jest klawiatura aktywna boxProgress1.invalidate(); } void MainView::exitClicked() { keyboard.setVisible (true); keyboard.invalidate(); //flexButtonEXIT.setVisible(true); //flexButtonEXIT.invalidate(); agemod = 0; } void MainView::WysylamBigos(uint16_t value) //float value - dla zmiennoprzecinkowej wartosci { //gauge1.setValue(value); //gauge1.invalidate(); //boxProgress1.setValue(value); //boxProgress1.invalidate(); //Unicode::snprintf(textArea1Buffer, TEXTAREA1_SIZE, "%d", value ); //textArea1.invalidate(); bigos2 = value; } void MainView::WysylamBigosFloat(float value2) //float value - dla zmiennoprzecinkowej wartosci { //gauge1.setValue(value); //gauge1.invalidate(); //boxProgress1.setValue(value); //boxProgress1.invalidate(); //Unicode::snprintf(textArea1Buffer, TEXTAREA1_SIZE, "%d", value ); //textArea1.invalidate(); dlugosc_materialu_View = value2; } void MainView::handleTickEvent() { if(zliczoneFlaga == 1) { dlugosc_materialu_View = dlugosc_ustawiona2; } Unicode::snprintfFloat(textArea_dlugosc_ustawionaBuffer, TEXTAREA_DLUGOSC_USTAWIONA_SIZE, "%0.1f", dlugosc_ustawiona2 ); textArea_dlugosc_ustawiona.invalidate(); WysylamBigosFloat(dlugosc_materialu_View); boxProgress1.setValue(dlugosc_materialu_View); boxProgress1.invalidate(); Unicode::snprintfFloat(textArea_dlugosc_materialuBuffer, TEXTAREA_DLUGOSC_MATERIALU_SIZE, "%0.1f", dlugosc_materialu_View ); textArea_dlugosc_materialu.invalidate(); boxProgress1.setRange(0, dlugosc_ustawiona2); boxProgress1.invalidate(); if((dlugosc_ustawiona2 - dlugosc_materialu_View) <= 0.01) { scalableImage_start.setVisible (true); scalableImage_start.invalidate(); scalableImage_start_1.setVisible (false); scalableImage_start_1.invalidate(); } } void MainView::startClicked() { presenter -> startClicked(); nawijanieAktywne_flaga = 1; scalableImage_start.setVisible (false); scalableImage_start.invalidate(); scalableImage_start_1.setVisible (true); scalableImage_start_1.invalidate(); zliczoneFlaga = 0; } void MainView::stopClicked() { presenter-> stopClicked(); nawijanieAktywne_flaga = 0; scalableImage_start.setVisible (true); scalableImage_start.invalidate(); scalableImage_start_1.setVisible (false); scalableImage_start_1.invalidate(); } void MainView::resetClicked() { if(nawijanieAktywne_flaga == 0) { presenter -> resetClicked(); } zliczoneFlaga = 0; } void MainView::WyslijFlage() { //start_flag; //presenter -> WysljFlage(); } void MainView::cofnij_clicked() { } void MainView::sendToScreen_zliczoneFlaga(int zerFlag) { zliczoneFlaga = zerFlag; } /// Add this function void MainView::flexButtonClickHandler(const touchgfx::TextButtonStyle< touchgfx::ImageButtonStyle< touchgfx::ClickButtonTrigger > > & b,const ClickEvent& e) { if(&b==&flexButtonCofnij) // button1 -> your button name { if (e.getType() == ClickEvent::PRESSED) { //touchgfx_printf("Button is pressed..\n"); presenter->setPin(); } else if (e.getType() == ClickEvent::RELEASED) { //touchgfx_printf("Button is released..\n"); presenter->resetPin(); } } }
View more

 

 Here a code Model.cpp:

#include <gui/model/Model.hpp> #include <gui/model/ModelListener.hpp> #ifndef SIMULATOR #include "main.h" #include "string.h" #include "EEPROM.h" #include <stdio.h> #include <stdlib.h> extern "C" { extern UART_HandleTypeDef huart2; extern TIM_HandleTypeDef htim4; extern __IO uint16_t dlugosc_materialu; extern __IO uint8_t dlugosc_ustawiona; extern __IO float dlugosc_materialu2; extern __IO float dlugosc_ustawiona2; extern float Pobierz_dlugosc(void); extern __IO uint8_t autoStartFlagaModel; extern __IO uint8_t zapisMierzonejFlagaModel; //extern __IO uint8_t zapisUstawionejFlagaModel; extern __IO float mnoznik_dlugosci; extern __IO float cofanie_wartosc; extern __IO int nawijanieAktywne_flaga; extern __IO int cofanieAktywne_flaga; extern __IO float dlugosc_ustawiona2_z_pamieci; extern __IO int zliczoneFlaga; } #endif Model::Model() : modelListener(0) { } void Model::tick() { modelListener->WysylamBigos(dlugosc_materialu); modelListener->WysylamBigosFloat(dlugosc_materialu2);// - dla zmiennoprzecinkowej wartosci modelListener->autoStartFlagGet(autoStartFlagaModel); modelListener->zapis_mierzonej_get(zapisMierzonejFlagaModel); modelListener->sendToScreen_Skala(mnoznik_dlugosci); modelListener->sendToScreen_cofanieWartosc(cofanie_wartosc); modelListener->sendToScreen_Dlugosc_ustawiona(dlugosc_ustawiona2_z_pamieci); modelListener->sendToScreen_zliczoneFlaga(zliczoneFlaga); } void Model::sendData(char *data) { //uint8_t * dlugosc; //dlugosc = (uint8_t *)&data; dlugosc_ustawiona = (uint8_t)atoi(data); //dlugosc_ustawiona2 = atof(data); dlugosc_ustawiona2 = atof(data); //Pobierz_dlugosc(); //dlugosc_ustawiona2 = (uint8_t)atoi(data); //static uint16_t cnt = 0; // Licznik wyslanych wiadomosci uint8_t dane[50]; // Tablica przechowujaca wysylana wiadomosc. uint16_t size = 0; // Rozmiar wysylanej wiadomosci //++cnt; // Zwiekszenie licznika wyslanych wiadomosci. size = sprintf(data, "Liczba wyslanych wiadomosci:"); // Stworzenie wiadomosci do wyslania oraz przypisanie ilosci wysylanych znakow do zmiennej size. HAL_UART_Transmit_IT(&huart2, dane, size); //dlugosc_ustawiona = 23; //Pobierz_dlugosc(dlugosc_ustawiona); } void Model::startClicked() { HAL_TIM_PWM_Start(&htim4, TIM_CHANNEL_1); //docelowo w tym miejscu zamiast wlaczenie TIMERA będziemy wysterowywali przekaźnik żeby wlaczyc silnik HAL_GPIO_WritePin(GPIOB, P1_Pin, GPIO_PIN_SET); //HAL_GPIO_WritePin(GPIOB, LED1_Pin, GPIO_PIN_SET); //Zapalamy LED jako wysterowanie prezkaźnika - do sygnalizacji w testach } void Model::stopClicked() { //HAL_TIM_PWM_Stop(&htim4, TIM_CHANNEL_1); // do testow - symulacja silnika HAL_GPIO_WritePin(GPIOB, P1_Pin, GPIO_PIN_RESET); //docelowo w tym miejscu zamiast wylaczenia TIMERA będziemy wysterowywali przekaźnik żeby wlaczyc silnik //HAL_GPIO_WritePin(GPIOB, LED1_Pin, GPIO_PIN_RESET); } void Model::resetClicked() { dlugosc_materialu = 0; dlugosc_materialu2 = 0; if(autoStartFlagaModel == 1) { //nawijanieAktywne_flaga = 1; HAL_GPIO_WritePin(GPIOB, P1_Pin, GPIO_PIN_SET); startClicked(); } } void Model::WyslijFlage() { //start_flag; nawijanieAktywne_flaga; //presenter -> WysljFlage(); } void Model::auto_start_set(uint8_t autoStartFlaga) { autoStartFlagaModel = autoStartFlaga; EEPROM_Write_NUM(5, 0, autoStartFlagaModel); } void Model::zapis_mierzonej_set(uint8_t zapisMierzonejFlaga) { zapisMierzonejFlagaModel = zapisMierzonejFlaga; EEPROM_Write_NUM(6, 0, zapisMierzonejFlagaModel); } /*void Model::zapis_ustawionej_set(uint8_t zapisUstawionejFlaga) { zapisUstawionejFlagaModel = zapisUstawionejFlaga; EEPROM_Write_NUM(7, 0, zapisUstawionejFlagaModel); }*/ void Model::sendToMain_Skala(char *data) { mnoznik_dlugosci = atof(data); EEPROM_Write_NUM(8, 0, mnoznik_dlugosci); } void Model::sendToMain_cofanie_wartosc(char *data) { cofanie_wartosc = atof(data); EEPROM_Write_NUM(9, 0, cofanie_wartosc); } void Model::cofnij_clicked() { //HAL_TIM_PWM_Start(&htim4, TIM_CHANNEL_1); //docelowo w tym miejscu zamiast wlaczenie TIMERA będziemy wysterowywali przekaźnik żeby wlaczyc silnik //if(cofanieAktywne_flaga == 1) //{ // HAL_GPIO_WritePin(GPIOB, P2_Pin, GPIO_PIN_SET); //} //HAL_Delay(1000); //cofanieAktywne_flaga; //cofanieAktywne_flaga = 1; } void Model::sendToMain_Dlugosc_ustawiona(char *data) { dlugosc_ustawiona2 = atof(data); EEPROM_Write_NUM(4, 0, dlugosc_ustawiona2); } void Model::sendToMain_cofnij(int cofnijf) { /*if(cofnijf == 1) { HAL_GPIO_WritePin(GPIOB, P2_Pin, GPIO_PIN_SET); } else { HAL_GPIO_WritePin(GPIOB, P2_Pin, GPIO_PIN_RESET); }*/ } void Model::setPin() { HAL_GPIO_WritePin(GPIOB, P2_Pin, GPIO_PIN_SET); } void Model::resetPin() { HAL_GPIO_WritePin(GPIOB, P2_Pin, GPIO_PIN_RESET); }
View more


Can you help me to find a faulty in my code? 

Hello. In this case i would check the touch panel handling/reading, is the sampleTouch-function getting steady and consistant coordinates every time it is called.

Br JTP