Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MakeCode issue with MakeCode sonar extension #439

Open
microbit-carlos opened this issue Jul 30, 2024 · 3 comments
Open

MakeCode issue with MakeCode sonar extension #439

microbit-carlos opened this issue Jul 30, 2024 · 3 comments
Assignees
Milestone

Comments

@microbit-carlos
Copy link
Collaborator

Issue:

Extension:

MakeCode pulseIn:

CODAL getPulseUs:

first step would be to write the SR04 code in C++ and see if we can replicate the issue where only 0-10cm is measured.

@microbit-carlos microbit-carlos added this to the v0.2.68 milestone Jul 30, 2024
@martinwork
Copy link
Collaborator

martinwork commented Aug 5, 2024

This is a C++ version of MakeCode code, except I separated CODAL and DAL pulseIn so I could choose either.

The pins (13, 14) are selected at the top of forever(). The distances are sent to DMESG.

The forever loop includes calls to reset both pins to digital inputs with pull down, immediately after receiving the pulse, and before the recommended 60ms pause between readings, which seems to give very good results.

Without resetting the pins, most values after the first are low and variable.

Example hex files: sonar-v2.zip

#include "MicroBit.h"

#ifndef MICROBIT_CODAL
  #ifdef CODAL_CONFIG_H
    #define MICROBIT_CODAL 1
  #else
    #define MICROBIT_CODAL 0
  #endif
#endif

#if MICROBIT_CODAL
#else
#define target_wait_us(us) wait_us(us)
#endif

void  sonarTrigger( MicroBitPin *trig);
int   pulseInCODAL( MicroBitPin *pin, bool high, int maxDuration = 2000000);
int   pulseInDAL( MicroBitPin *pin, bool high, int maxDuration = 2000000);
int   pulseIn( MicroBitPin *pin, bool high, int maxDuration = 2000000);
void  resetPin( MicroBitPin *pin);
void  forever();


MicroBit uBit;

int main()
{
  uBit.init();
  uBit.serial.setTxBufferSize(254);
  create_fiber( forever);
  release_fiber();
  return 0;
}


void forever()
{
    MicroBitPin *pinTrig = &uBit.io.P13;
    MicroBitPin *pinEcho = &uBit.io.P14;

    while (true)
    {
      DMESG( "");

      sonarTrigger( pinTrig);

      int cm = pulseInCODAL( pinEcho, true, 500 * 58) / 58;
      //int cm = pulseInDAL( pinEcho, true, 500 * 58) / 58;
      DMESG( "cm:%d", cm);

      resetPin( pinEcho);
      resetPin( pinTrig);

      uBit.sleep( 60);
    }
}


void sonarTrigger( MicroBitPin *trig)
{
  //DMESG("sonarTrigger(%p)", trig);
#if MICROBIT_CODAL
  trig->setPull( PullMode::None);
#else
  trig->setPull( PullNone);
#endif
  trig->setDigitalValue(0);
  target_wait_us(2);
  trig->setDigitalValue(1);
  target_wait_us(10);
  trig->setDigitalValue(0);
}


int pulseInCODAL( MicroBitPin *pin, bool high, int maxDuration) {
#if MICROBIT_CODAL
  //DMESG("pulseInCODAL(%p)", pin);
  pin->setPolarity(high ? 1 : 0);
  int period = pin->getPulseUs(maxDuration);
  // timeout
  if (DEVICE_CANCELLED == period)
      return 0;
  // success!
  return period;
#else
  return 0;
#endif
}


int pulseInDAL( MicroBitPin *pin, bool high, int maxDuration) {
  //DMESG("pulseInDAL(%p)", pin);
  int pulse = high ? 1 : 0;
  uint64_t tick =  system_timer_current_time_us();
  uint64_t maxd = (uint64_t)maxDuration;
  while(pin->getDigitalValue() != pulse)
  {
      if(system_timer_current_time_us() - tick > maxd)
          return 0;
  }

  uint64_t start =  system_timer_current_time_us();
  while(pin->getDigitalValue() == pulse)
  {
      if(system_timer_current_time_us() - tick > maxd)
          return 0;
  }
  uint64_t end =  system_timer_current_time_us();
  return end - start;
}


int pulseIn( MicroBitPin *pin, bool high, int maxDuration) {
#if MICROBIT_CODAL
  return pulseInCODAL( pin, high, maxDuration);
#else
  return pulseInDAL( pin, high, maxDuration);
#endif
}


void resetPin( MicroBitPin *pin)
{
  int scratch;
//  scratch = pin->getAnalogValue();
  scratch = pin->getDigitalValue();
#if MICROBIT_CODAL
  pin->setPull( PullMode::Down);
#else
  pin->setPull( PullDown);
#endif
}

@martinwork
Copy link
Collaborator

martinwork commented Aug 5, 2024

Even without the resetPin calls in the forever loop above, CODAL currently resets the echo pin and creates a new PulseIn for each call to getPulseUs (see why below).

I modified getPulseUs to avoid the reset. I'm not sure if it helped, but it was not nearly as good as "manually" resetting the pins before the pause between readings.

I don't know why it's different. Could it be better for the sensor?

Details of why the reset occurs...

https://github.com/lancaster-university/codal-nrf52/blob/8802eb49140e0389e535cb6160d9080efd951ba7/source/NRF52Pin.cpp#L927

There's a call to getDigitalValue to ensure the pin is in digital input mode.

But since MakeCode v5, CODAL v0.2.40 the test at the top of getDigitalValue has been changed to check for a locked peripheral obj. The PulseIn is an obj but it's not locked, so the call disconnects the PulseIn and resets the interrupt behaviour, which is noticed on the next line in getPulseUs.

Here's the change at line 335
lancaster-university/codal-nrf52@24ea962

Note that the code at line 338 has gone, although the comment about fast switching remains.

https://github.com/lancaster-university/codal-nrf52/blob/8802eb49140e0389e535cb6160d9080efd951ba7/source/NRF52Pin.cpp#L274

@martinwork
Copy link
Collaborator

So fast input/output switching support has been lost (for one wire sensors, or sonar sensors that use a single pin?)
lancaster-university/codal-nrf52@f050e2e

@microbit-carlos microbit-carlos self-assigned this Aug 23, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants