Code Monkey home page Code Monkey logo

Comments (4)

bjoernQ avatar bjoernQ commented on August 27, 2024

That's an interesting project!

Seems like something is blocking (for too long) and the BLE stack doesn't get a chance to process the HCI packets.

I used the async_ble example and just added another (very simple) task:

#[embassy_executor::task]
async fn second_task() {
    loop {
        Timer::after(Duration::from_secs(1)).await;
        println!("ping");
    }
}

And launch the task together with the BLE task (spawner.spawn(second_task()).ok();)

I see the output printed from the second_task and can interact with the device via BLE without issues.

Maybe you could try to simplify your second task step by step until to get back to a "working" state.

from esp-wifi.

WJKPK avatar WJKPK commented on August 27, 2024

Thank you very much for your answer!
I attempted to address the problem by implementing the following simplified task

#[embassy_executor::task]
pub async fn run(thermo: ThermoControl<ThermoToggler>) {
    loop {
        let requested_state = SHARED.wait().await;
        let mut i = 0;
        loop {
            i += 1;
            TEMPERATURE_SIGNAL.signal(i);
            Timer::after(Duration::from_secs(1)).await;
        }
    }
}

in order to signal notifier closure called by AttributeServer

let mut notifier = async || {
    let temperature = TEMPERATURE_SIGNAL.wait().await;
    let mut data = [0u8; 2];
    let temperature: &[u8] = unsafe { any_as_u8_slice(&temperature)};
    data.copy_from_slice(temperature);
    NotificationData::new(temperature_handle, &data)
};
srv.run(&mut notifier).await.unwrap();

Despite implementing this approach, the problem still persists - the symptoms are the same as before

from esp-wifi.

bjoernQ avatar bjoernQ commented on August 27, 2024

I tried to resemble what your code does by modifying the async_ble.rs example to use a second task and using Signal ... still works for me

#![no_std]
#![no_main]
#![feature(type_alias_impl_trait)]
#![feature(async_closure)]

use core::cell::RefCell;

use bleps::{
    ad_structure::{
        create_advertising_data, AdStructure, BR_EDR_NOT_SUPPORTED, LE_GENERAL_DISCOVERABLE,
    },
    async_attribute_server::AttributeServer,
    asynch::Ble,
    attribute_server::NotificationData,
    gatt,
};
use embassy_executor::Executor;
use embassy_executor::_export::StaticCell;
use embassy_sync::{blocking_mutex::raw::CriticalSectionRawMutex, signal::Signal};
use embassy_time::{Duration, Timer};
use embedded_hal_async::digital::Wait;
use esp_backtrace as _;
use esp_println::{logger::init_logger, println};
use esp_wifi::{
    ble::controller::asynch::BleConnector, initialize, EspWifiInitFor, EspWifiInitialization,
};
use examples_util::hal;
use examples_util::BootButton;
use hal::{
    clock::{ClockControl, CpuClock},
    embassy,
    peripherals::*,
    prelude::*,
    radio::Bluetooth,
    timer::TimerGroup,
    Rng, Rtc, IO,
};

static SIGNAL: Signal<CriticalSectionRawMutex, u32> = Signal::new();

#[embassy_executor::task]
async fn second_task(mut pin: BootButton) {
    let mut i = 0;

    loop {
        pin.wait_for_rising_edge().await.unwrap();
        //Timer::after(Duration::from_millis(3000)).await;
        println!("ping");
        SIGNAL.signal(i);
        i += 1;
    }
}

#[embassy_executor::task]
async fn run(init: EspWifiInitialization, mut bluetooth: Bluetooth) {
    let connector = BleConnector::new(&init, &mut bluetooth);
    let mut ble = Ble::new(connector, esp_wifi::current_millis);
    println!("Connector created");

    loop {
        println!("{:?}", ble.init().await);
        println!("{:?}", ble.cmd_set_le_advertising_parameters().await);
        println!(
            "{:?}",
            ble.cmd_set_le_advertising_data(
                create_advertising_data(&[
                    AdStructure::Flags(LE_GENERAL_DISCOVERABLE | BR_EDR_NOT_SUPPORTED),
                    AdStructure::ServiceUuids16(&[Uuid::Uuid16(0x1809)]),
                    AdStructure::CompleteLocalName(examples_util::SOC_NAME),
                ])
                .unwrap()
            )
            .await
        );
        println!("{:?}", ble.cmd_set_le_advertise_enable(true).await);

        println!("started advertising");

        let mut rf = |_offset: usize, data: &mut [u8]| {
            data[..20].copy_from_slice(&b"Hello Bare-Metal BLE"[..]);
            17
        };
        let mut wf = |offset: usize, data: &[u8]| {
            println!("RECEIVED: {} {:x?}", offset, data);
        };

        let mut wf2 = |offset: usize, data: &[u8]| {
            println!("RECEIVED: {} {:x?}", offset, data);
        };

        let mut rf3 = |_offset: usize, data: &mut [u8]| {
            data[..5].copy_from_slice(&b"Hola!"[..]);
            5
        };
        let mut wf3 = |offset: usize, data: &[u8]| {
            println!("RECEIVED: Offset {}, data {:x?}", offset, data);
        };

        gatt!([service {
            uuid: "937312e0-2354-11eb-9f10-fbc30a62cf38",
            characteristics: [
                characteristic {
                    uuid: "937312e0-2354-11eb-9f10-fbc30a62cf38",
                    read: rf,
                    write: wf,
                },
                characteristic {
                    uuid: "957312e0-2354-11eb-9f10-fbc30a62cf38",
                    write: wf2,
                },
                characteristic {
                    name: "my_characteristic",
                    uuid: "987312e0-2354-11eb-9f10-fbc30a62cf38",
                    notify: true,
                    read: rf3,
                    write: wf3,
                },
            ],
        },]);

        let mut srv = AttributeServer::new(&mut ble, &mut gatt_attributes);

        let mut notifier = async || {
            let x = SIGNAL.wait().await;
            let mut data = [0u8; 13];
            data.copy_from_slice(b"Notification0");
            data[data.len() - 1] = (x as u8) + b'0';
            NotificationData::new(my_characteristic_handle, &data)
        };

        srv.run(&mut notifier).await.unwrap();
    }
}

static EXECUTOR: StaticCell<Executor> = StaticCell::new();

#[entry]
fn main() -> ! {
    init_logger(log::LevelFilter::Info);

    let peripherals = Peripherals::take();

    let system = examples_util::system!(peripherals);
    let mut peripheral_clock_control = system.peripheral_clock_control;
    let clocks = examples_util::clocks!(system);
    examples_util::rtc!(peripherals);

    let timer = examples_util::timer!(peripherals, clocks, peripheral_clock_control);
    let init = initialize(
        EspWifiInitFor::Ble,
        timer,
        Rng::new(peripherals.RNG),
        system.radio_clock_control,
        &clocks,
    )
    .unwrap();

    let button = examples_util::boot_button!(peripherals);

    // Async requires the GPIO interrupt to wake futures
    hal::interrupt::enable(
        hal::peripherals::Interrupt::GPIO,
        hal::interrupt::Priority::Priority1,
    )
    .unwrap();

    let bluetooth = examples_util::get_bluetooth!(peripherals);

    let timer_group0 = TimerGroup::new(peripherals.TIMG0, &clocks, &mut peripheral_clock_control);
    embassy::init(&clocks, timer_group0.timer0);
    let executor = EXECUTOR.init(Executor::new());
    executor.run(|spawner| {
        spawner.spawn(run(init, bluetooth)).ok();
        spawner.spawn(second_task(button)).ok();
    });
}

from esp-wifi.

WJKPK avatar WJKPK commented on August 27, 2024

Thank you! Thanks to you, I realized that I hadn't enabled async and ble features while building the software. When I incorporated these, everything worked as expected.

from esp-wifi.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.