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 II

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);
 }
}

 

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

 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();
		}
	}
}

 

 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);
}


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