Sending characters via Bluetooth Low Energy to HC-05

Hello, I am trying to build an app that’s is going to be a controller for a car made in an arduino project. I’m using an HC-05 Bluetooth module that connects correctly only via Bluetooth Low Energy. Like a controller should work, I want o send characters like “F” so the car can move foward, “B” to move backwards etc.. As the block diagram shows, I am using the WriteString block to send the characters, but the car does not receive correctly, although it’s connected to the mobile phone.


BluetoothRemoteControl_BLE.aia (237.2 KB)

Dear @Frytz, the car does not receive correctly means:

  1. it receives rubbish? (in this case could be a problem of baudrate between CPU board and HC05)
  2. does not receive anything ? (in this case the problem is related to a lack of communication at all).

Case 1) check whether you find somewhere which is the baudrate at which the HC05 wants to work towards the CPU board (datasheet or other documentation)
Case 2) start praying...
Jokes apart, the BLE is a real nightmare, so first of all verify if the service and characteristics UUID are correct for the HC05 you are using. To check this there are really a lot of topics on this matter in the forum. Do a search with the tags HC05 and BLE.
Many users have fought with the same problem in the past weeks, so you'll find plenty of comments and hints to get a solution.
Moreover, to have a greater possibility to get help, please post also the .ino file, so to have a check on that part of the code, as well.
Best wishes

EDIT: try to have a look here:

The project works on the Serial Bluetooth Terminal, so I think that the arduino sketch, and the all the physical component is okay. I notice that Mr. Edumarca uses WriteStringWithResponse, but I still don't understand where he got the green block TxtMessage.Text from, maybe I'm using other version of the BLE Extension. Don't know if it can help but here's the arduino code (I do not have the .ino file itself in this computer). Thank you!

#include <avr/io.h>
#include <avr/interrupt.h>


#define TRIG1 PD4
#define ECHO1 PD2 // (INT0)
#define TRIG2 PD5
#define ECHO2 PD3 // (INT1)
#define LED_VERDE    PC0
#define LED_VERMELHO PC1
#define BUZZER       PC2
#define LED_PISCA    PC3 // O LED de 1HZ

// motores dianteiros
#define IN1 PD6 //frente dir
#define IN2 PD7 //ré dir
#define IN3 PB3 //frente esq
#define IN4 PB4 //ré esq
//motores traseiros
#define IN5 PB5 //frente dir
#define IN6 PB0// ré dir
#define IN7 PC4  //frente esq
#define IN8 PC5 //ré esq
// enables
#define ENA  PB2 //rodas esquerdas
#define ENB  PB1 //rodas direitas

#define calibrador 40




volatile int echoFlag1 = 0, echoFlag2 = 0;
volatile uint8_t pulso1 = 0, pulso2 = 0; // limitei pulso a 8 bits para nao bloquear timer2
volatile char comando_recebido = '0'; // '0' para começar parado
volatile int modo = 0;
volatile int vel1, vel2;
volatile int flag_comando;


 void Usart_init() {
        unsigned int ubrr;
        ubrr = 103;
        UBRR0H = (unsigned char)(ubrr >> 8);
        UBRR0L = (unsigned char)ubrr;
        UCSR0B = 0b10011000; // Habilita receptor e interrupção
        UCSR0C = 0b00000110; //8 bits de dados
 }



     ISR(USART_RX_vect) {
       char letra = UDR0;
        flag_comando = 0;
       if (letra == '\n' || letra == '\r' || letra == ' ') {
        return; 
    }
        if (letra == 'A'){
            modo = 1; // automatico  
        }
        else if (letra == 'M'){
            modo = 0; // manual
            comando_recebido = '0';
        }
        else if (modo == 0) { // apenas recebe comandos no modo bluetooth
            comando_recebido = letra;
        }
    }

void inicio () {
    
    DDRD = 0b11110000; // triggers e motores como saída
    DDRC = 0b00111111; // LEDs e buzzer como saída
    DDRB = 0b00111111; // pinos motores e enables como saída

    TCCR1A = 0b10100001;
    TCCR1B = 0b00000011;
    OCR1A = 0; // velocidade inicial 0
    OCR1B = 0;

    TCCR2A = 0b00000000; // modo normal
    TCCR2B = 0b00000111;// prescaler 1024
    TCNT2 = 0; // contador a zero

    EICRA = 0b00000101; // qualquer mudança logica
    EIMSK = 0b00000011; //  INT0 e INT1

    Usart_init();
    sei();
}

    void motores_frente() {

    PORTD |= (1 << IN1);
    PORTD &= ~(1 << IN2);
    PORTB |= (1 << IN3);
    PORTB &= ~(1 << IN4);
    PORTB |= (1 << IN5);
    PORTB &= ~(1 << IN6);
    PORTC |= (1 << IN7);
    PORTC &= ~(1 << IN8);
}

void motores_re() {

    PORTD |= (1 << IN2);
    PORTD &= ~(1 << IN1);
    PORTB |= (1 << IN4);
    PORTB &= ~(1 << IN3);
    PORTB |= (1 << IN6);
    PORTB &= ~(1 << IN5);
    PORTC |= (1 << IN8);
    PORTC &= ~(1 << IN7);
}



void virar_direita() {
   //direita anda devagar
    PORTD |= (1 << IN1); 
    PORTD &=~ (1 << IN2);  
    PORTB |= (1 << IN5); 
    PORTB &=~ (1 << IN6);  
   // esquerda anda mais depressa  
    PORTB |= (1 << IN3);  
    PORTB &=~ (1 << IN4); 
    PORTC |= (1 << IN7);  
    PORTC &=~ (1 << IN8); 
    
    OCR1A = vel1/2;
    OCR1B = vel2;
}

void virar_esquerda() {
    //direita anda mais depressa 
    PORTD |= (1 << IN1);  
    PORTD &=~ (1 << IN2);
    PORTB |= (1 << IN5);  
    PORTB &=~ (1 << IN6); 
   // esquerda anda mais devagar
    PORTB |= (1 << IN3); 
    PORTB &=~ (1 << IN4);  
    PORTC |= (1 << IN7); 
    PORTC &=~ (1 << IN8);  

    OCR1A = vel1;
    OCR1B = vel2 /2;
}
   
void motores_stop() {

    PORTD &= ~(1 << IN2);
    PORTD &= ~(1 << IN1);
    PORTB &= ~(1 << IN3);
    PORTB &= ~(1 << IN4);
    PORTB &= ~(1 << IN6);
    PORTB &= ~(1 << IN5);
    PORTC &= ~(1 << IN7);
    PORTC &= ~(1 << IN8);
    OCR1A = 0; // velocidade 0
    OCR1B = 0;

}

void modo_lento() {
    vel1 = 100 - calibrador; // velocidade lenta
    vel2 = 100;
    OCR1A = vel1;
    OCR1B = vel2;
}

void modo_medio() {

    vel1 = 170  - calibrador; // velocidade média
    vel2 = 170;
    OCR1A = vel1;
    OCR1B = vel2;

}

void modo_rapido() {

    vel1 = 220  - calibrador; // velocidade rápida
    vel2 = 220;
    OCR1A = vel1;
    OCR1B = vel2;
}
 void guarda_velocidade (){
    OCR1A = vel1;
    OCR1B = vel2;
 }


void delay_10us() {

    OCR0A = 159; // valor calculado para gerar 10us
    TCNT0 = 0; // zera o timer0
    TCCR0A = 0b00000010; // modo CTC
    TCCR0B = (1 << CS00);  // prescaler 1
    TIFR0 = (1 << OCF0A);  // limpa a flag
    while ((TIFR0 & (1 << OCF0A)) == 0); //Aguarda  
    TCCR0B = 0;  // para o timer0          
    }

void delay_1ms(unsigned int a) {
        for (unsigned int i = 0; i < a; i++) { // loop para gerar atraso de a ms
        OCR0A = 249; // valor calculado para gerar 1ms
        TCNT0 = 0;
        TCCR0A = 0b00000010;            
        TCCR0B = (1 << CS01) | (1 << CS00); // prescaler 64
        TIFR0 = (1 << OCF0A); // limpa a flag
        while (!(TIFR0 & (1 << OCF0A)));   // aguarda
        TCCR0B = 0;        // para o timer0                  
    }
}  

void sinalpulso(int pinotrigger) {
    PORTD |= (1 << pinotrigger);   // liga o trigger
    delay_10us();      // espera 10us      
    PORTD &= ~(1 << pinotrigger);  // desliga o trigger
}

ISR(INT0_vect) {
    if (PIND & (1 << ECHO1)) { // verifica se é borda de subida
        TCNT2 = 0;  // zera o timer2  
        echoFlag1 = 1;  // borda de subida
    }
    else if (echoFlag1 == 1) { // verifica se é borda de descida
        pulso1 = TCNT2; // armazena o tempo do pulso
        echoFlag1 = 0;  // reseta a flag    
    }

}

ISR(INT1_vect) { // mesma lógica do INT0
    if (PIND & (1 << ECHO2)) {
        TCNT2 = 0;
        echoFlag2 = 1;
    }
    else if (echoFlag2 == 1) {
       pulso2 = TCNT2;
       echoFlag2 = 0;
    }

}



void sistema_alerta (int distancia) {
    if (distancia <= 20) { // verifica a distância é menor ou igual a 10 cm
        PORTC |= (1 << BUZZER); // liga o buzzer
        PORTC &= ~((1 << LED_VERDE)); // desliga o led verde
    }

    else if (distancia <= 30) {
        PORTC |= (1 << LED_VERMELHO); // liga o led vermelho sem piscar
        PORTC ^= (1 << BUZZER);
        PORTC &= ~((1 << LED_VERDE)); // desliga o resto
    }

    else if (distancia <= 50) {
        PORTC |= (1 << LED_VERDE); // liga led verde
        PORTC &= ~((1 << LED_VERMELHO) | (1 << BUZZER));
    }

    else {
        PORTC &= ~((1 << LED_VERDE) | (1 << LED_VERMELHO) | (1 << BUZZER)); // desliga tudo
    }
}

void led1Hz_ledSA (int obstaculo){
      static int contador_led = 0;
        contador_led++;
        if (contador_led >= 4 ){
            PORTC ^= (1 << LED_PISCA); // tooggle do led
            contador_led = 0;
            }
        if (obstaculo == 1){ // apenas acionado quase esteja obstaculo no sistema autonomo
               PORTC ^= (1 << LED_VERMELHO); // pisca o led vermelho
        }
    }



void sistema_autonomo(int d){
    if (d > 50) {
        motores_frente();
        modo_rapido();
    }
    else if (d > 40) {
        motores_frente();
        modo_medio();
    }
    else if (d > 20) {
        motores_frente();
        modo_lento();
    }
    else {
        motores_stop();
        motores_re();
        modo_medio();
        for (int i = 0; i < 6; i++){
            delay_1ms (125);
            led1Hz_ledSA(1);
        }

        motores_stop();
        for (int i = 0; i < 2; i++){ 
            delay_1ms(125);
            led1Hz_ledSA(1);
        }

        virar_direita();
        modo_medio();
         for (int i = 0; i < 10; i++){
            delay_1ms (125);
            led1Hz_ledSA(1);
        }
        motores_stop();
        for (int i = 0; i < 2; i++){ 
            delay_1ms(125);
            led1Hz_ledSA(1);
        }

    }
}


void sistema_bluetooth(int frente, int tras) {
    if (frente<=20 && (comando_recebido == 'F')) { //proibe de andar para frente se tiver obstaculo mesmo que se carregue no F
        motores_stop();
    }
    else if (tras<=20 && (comando_recebido == 'B')) { //proibe de andar para tras se tiver obstaculo mesmo que se carregue no B
        motores_stop();
    }
    else {
    switch (comando_recebido) {
        case 'F':

            motores_frente();
            guarda_velocidade();
            break;
        case 'B':
            motores_re();
            guarda_velocidade();
            break;
        case 'L':
            virar_esquerda();
            guarda_velocidade();
            break;
        case 'R':
            virar_direita();
            guarda_velocidade();
            break;
        case 'S':
            motores_stop();
            break;
        case '1':
            modo_lento();
            break;
        case '2':
            modo_medio();
            break;
        case '3':
            modo_rapido();    
            break;
    }
    }
}

 int main() {

    int distancia1, distancia2, distanciaMin;
    inicio();
    modo_medio();
    while (1) {
        
        sinalpulso(TRIG1);
        delay_1ms(62);
        distancia1 = (pulso1 * 64) / 58;
       
        sinalpulso(TRIG2);
        delay_1ms(62);
        distancia2 = (pulso2 * 64) / 58;

       if (distancia2 == 0) { // if else para verificar a menor distancia e 0 como sem leitura
            distanciaMin = distancia1;
       }
        else if (distancia1 == 0) {
            distanciaMin = distancia2;
        } else if (distancia1 < distancia2) {
            distanciaMin = distancia1;
        } else {
            distanciaMin = distancia2;
        }

    sistema_alerta(distanciaMin);

  if (distanciaMin <= 20 ) {
            led1Hz_ledSA(1); // Atualiza Azul + Pisca Vermelho
        } else {
            led1Hz_ledSA(0); // Atualiza Azul + Desliga Vermelho
        }

/*if (modo == 0){
    flag_comando++;
     if (flag_comando > 4){
        comando_recebido = 'S';
        flag_comando = 0;
    }
}*/



    if (modo == 1) { // modo automatico

    sistema_autonomo(distancia1);

    }
    else { // modo bluetooth

    sistema_bluetooth(distancia1, distancia2);

    }



    }

}

(Added ``` lines for code readability - ABG)

The green block at

is a reference to the text in a Textbox component.
That app wants to allow the user to type in what to send, so it has a Textbox component for that purpose.

It has no relevance for your controller app.

Hm I see, thanks for the clarification!

Hi, the latest BLE extension is retrievable here:

The green .text is most probably the text that the user sends to his Arduino system, tehrefore you can put in that block exactly the command that you want to send (be careful to append the \n to terminate the string).
Last hint is: for your head's sanity ( :grin:), please start with a super simple .ino, just trying the connection and displaying on the Serial Monitor of the Arduino system (i.e. connected to the development PC) what it is receiving. After you are done with that, you can add everything you want, but, believe me, is far better to start in a simpler way.
If you still get lost, you can have a look to @ChrisWard's web site: professorcad.co.uk where you can find a huge amount of examples.

Now I remember also another thing: the HC05 BLE must be set in the proper BLE functioning mode (using the AT commands) It should be set as "peripheral", and not "central" (or visa-versa, unfortunately I'm not pretty sure which one of the two, but for sure if the HC05 is set in the wrong mode it won't work) :fearful:

EDIT:here below an interesting post
https://medium.com/@yostane/using-the-at-09-ble-module-with-the-arduino-3bc7d5cb0ac2

EDIT 2: why you send the commands using the block Make a list + command and not only sending the command ?