5 years, 11 months ago.

run TCPServer and PressButton event at the same time

I have problem in my code. Please help! I want to run TCPServer for send data to web browser and I want to action when press the button .

[Running mode] I pressed the button but no action until I call data from TCPServer with web browser.

I use MBED-OS 5.x and STM32 f746zg /media/uploads/t2dear_ict/aaaaaa.jpg

This is my code

#include "mbed.h"
#include "EthernetInterface.h"

EthernetInterface net;
TCPServer srv;
TCPSocket client_sock;
SocketAddress client_addr;
char *wbuffer = new char[256];

InterruptIn button1(USER_BUTTON);
volatile bool button1_pressed = false; // Used in the main loop
volatile bool button1_enabled = true; // Used for debouncing
Timeout button1_timeout; // Used for debouncing

// Enables button when bouncing is over
void button1_enabled_cb(void)
{
    button1_enabled = true;
}

// ISR handling button pressed event
void button1_onpressed_cb(void)
{
    if (button1_enabled) { // Disabled while the button is bouncing
        button1_enabled = false;
        button1_pressed = true; // To be read by the main loop        
        button1_timeout.attach(callback(button1_enabled_cb), 0.3); } // Debounce time 300 ms    
}

void doButton()
{   
    printf("BUTTON PRESSED\r\n");
} 


int main() {    
    net.connect();
    const char *ip = net.get_ip_address();
    printf("IP address: %s\r\n", ip ? ip : "No IP\r\n");
    printf("NetMask: %s\r\n", net.get_netmask());
    printf("Gateway Address: %s\r\n", net.get_gateway());
    printf("Mac Address: %s\r\n", net.get_mac_address());
    printf("Ethernet Setup OK\r\n");            
        
    srv.open(&net);
    srv.bind(net.get_ip_address(), 80);
    srv.listen(1); 
    printf("TCP Server open success\r\n");      
    
    button1.fall(callback(button1_onpressed_cb)); // Attach ISR to handle button press event 

    while(1) {    
            printf("TCP Server Listen\r\n");
            srv.accept(&client_sock, &client_addr);
            printf("Accepted %s:%d\n", client_addr.get_ip_address(), client_addr.get_port());
                            
            strcpy(wbuffer, "HELLO WORLD");
                    
            client_sock.send(wbuffer, strlen(wbuffer));
            client_sock.recv(wbuffer, 10000);
            
            client_sock.close();
            delete[] wbuffer;
        
        if (button1_pressed) { // Set when button is pressed
            button1_pressed = false;
            doButton();           
        }
    }//end while    
    
}

Sorry for my english language

Thank you so much.

1 Answer

5 years, 11 months ago.

Hello Teerawat,

You can make the push button operational by handling it in a concurrent thread as below:

#include "mbed.h"
#include "EthernetInterface.h"

//#define USER_BUTTON p21

EthernetInterface   net;
TCPServer           srv;
TCPSocket           client_sock;
SocketAddress       client_addr;
char*               wbuffer = new char[256];
InterruptIn         button1(USER_BUTTON);
volatile bool       button1_pressed = false;    // Used in the main loop
volatile bool       button1_enabled = true;     // Used for debouncing
Timeout             button1_timeout;            // Used for debouncing
Thread              button1Thread;

// Enables button when bouncing is over
void button1_enabled_cb(void)
{
    button1_enabled = true;
}

// ISR handling button pressed event
void button1_onpressed_cb(void)
{
    if (button1_enabled)
    {                           // Disabled while the button is bouncing
        button1_enabled = false;
        button1_pressed = true; // To be read by the button1Loop
        button1_timeout.attach(callback(button1_enabled_cb), 0.3);  // Debounce time 300 ms
    }
}

void doButton()
{
    printf("BUTTON PRESSED\r\n");
}

void button1Loop()
{
    while (1)
    {
        if (button1_pressed)
        {
            button1_pressed = false;
            doButton();
        }
    }
}

int main()
{
    net.connect();
    const char*     ip = net.get_ip_address();
    printf("IP address: %s\r\n", ip ? ip : "No IP\r\n");
    printf("NetMask: %s\r\n", net.get_netmask());
    printf("Gateway Address: %s\r\n", net.get_gateway());
    printf("Mac Address: %s\r\n", net.get_mac_address());
    printf("Ethernet Setup OK\r\n");

    srv.open(&net);
    srv.bind(net.get_ip_address(), 80);
    srv.listen(1);
    printf("TCP Server open success\r\n");

    button1.mode(PullUp);
    button1.fall(callback(button1_onpressed_cb));   // Attach ISR to handle button press event
    button1Thread.start(button1Loop);

    while (1)
    {
        printf("TCP Server Listen\r\n");
        srv.accept(&client_sock, &client_addr);
        printf("Accepted %s:%d\n", client_addr.get_ip_address(), client_addr.get_port());

        strcpy(wbuffer, "HELLO WORLD");

        client_sock.send(wbuffer, strlen(wbuffer));
        client_sock.recv(wbuffer, 10000);

        client_sock.close();
        delete[] wbuffer;
    }   //end while
}

But this will not make the program act as you wished. Because it's always the client (in this case a web browser) who initiates a data exchange, I think that's even impossible to achieve. The server can just wait (listen) for that to happen (in this case by executing the srv.accept(&client_sock, &client_addr); statement in context of the main thread).

Accepted Answer

To control your NUCLEO-F746ZG board (while it is hosting a TCP server) from a TCP client (web browser) you can try the https://os.mbed.com/users/hudakz/code/WebSwitch_mbed-os/ example program.

posted by Zoltan Hudak 08 May 2018

Thank you for your answer. Your code is successful. And learning more the THREAD subject. https://os.mbed.com/docs/v5.8/reference/thread.html

posted by Teerawat Khamsat 10 May 2018