Page 2 of 2

Re: Set the EXT for HC-SR04

Posted: Wed Sep 16, 2015 12:59 pm
by afranzese
alex31 wrote:I have implemented a driver (chibios 2.6) for the HC-SR04 based on PWM for pulse generation and ICU for response measure,
it works well without hacking CH_FREQUENCY, and with minimal cpu usage.
Can post the source if interested.

Alexandre


We will appreciate!
Can you check also my code?
for PWM configuration i've used

Code: Select all

static PWMConfig pwmcfg = {
  100000,                                    /* 100kHz=10us PWM clock frequency.   */
  2,                                    /* Initial PWM period 20uS.       */
  pwmpcb,
  {
   {PWM_OUTPUT_ACTIVE_HIGH, pwmc1cb},
   {PWM_OUTPUT_DISABLED, NULL},
   {PWM_OUTPUT_DISABLED, NULL},
   {PWM_OUTPUT_DISABLED, NULL}
  },
  0,
  0
};


for ICU

Code: Select all

static ICUConfig icucfg = {
  ICU_INPUT_ACTIVE_HIGH,
  100000,                                    /* 100kHz ICU clock frequency.   */
  icuwidthcb,
  icuperiodcb,
  NULL,
  ICU_CHANNEL_1,
  0
};

and in the main

Code: Select all

pwmStart(&PWMD1, &pwmcfg);
 
  palSetPadMode(GPIOA, 9, PAL_MODE_ALTERNATE(1));
  icuStart(&ICUD3, &icucfg);
  palSetPadMode(GPIOC, 6, PAL_MODE_ALTERNATE(2));
  pwmEnableChannel(&PWMD1, 0, PWM_PERCENTAGE_TO_WIDTH(&PWMD1, 5000));
  icuStartCapture(&ICUD3);
  pwmDisableChannel(&PWMD1, 0);
  pwmStop(&PWMD1);
  icuStopCapture(&ICUD3);
  icuStop(&ICUD3);


Giovanni wrote:Then there some other problem that is not immediately apparent to me. I can suggest to keep the code simple and add things one by one, that code looks very convoluted for the simple thing you are trying to accomplish.

If you need to measure an interval then you just need the system time.

1) Generate the pulse.
2) Read time.
3) Wait for the raising front (polling, not EXT).
4) Read time again and make the difference.

Once the simple thing works then you may try a more complex approach.

Giovanni


You gave me the same suggestion, but i used get time function and get elapsed time function in this way:

Code: Select all

palSetPad(port, pad);
chThdSleepMicroseconds(10);  //this time is taken by sensor datasheet
palClearPad(port, pad);
deltatime=chVTGetSystemTime();
while(Signal echo is low)
chVTTimeElapsedSinceX(deltatime);


and which is the difference between chVTGetSystemTime and chVTGetSystemTimeX

Re: Set the EXT for HC-SR04

Posted: Wed Sep 16, 2015 6:26 pm
by giannir1988
alex31 wrote:I have implemented a driver (chibios 2.6) for the HC-SR04 based on PWM for pulse generation and ICU for response measure,
it works well without hacking CH_FREQUENCY, and with minimal cpu usage.
Can post the source if interested.

Alexandre


Please! upload your code!

Tis is my code:

Code: Select all

*  LIBRERIA PER L'UTILIZZO DEL SENSORE AD ULTRASUONI
 *
 *  Questa versione della libreria utilizza una While per
 *  rilevare il tempo di attraversamento del suono
 ----------------------------------------------------------*/
#include "ch.h"
#include "hal.h"
  //Definisce i pin di montaggio sensori
#define T_PORT GPIOA
#define T_PIN GPIOA_PIN10
#define E_PORT GPIOB
#define E_PIN GPIOB_PIN5
/*-------------------------------
 * DEFINIZIONE DEI PARAMETRI
 * ------------------------------ */


//PROCEDURA DI INIZIALIZZAZIONE
void usInit(void){

  //Definizione delle modalità

  palSetPadMode(T_PORT, T_PIN, PAL_MODE_OUTPUT_PUSHPULL);
  palSetPadMode(E_PORT, E_PIN, PAL_MODE_INPUT_PULLDOWN);

}


/*-------------------------------
 * PROCEDURE PERSONALI
 --------------------------------*/

//PROCEDURA PER LA LETTURA DEL TEMPO DI PERCORRENZA
float read_time_distance(BaseSequentialStream* chp){

  //definizione delle variabii
    systime_t start = 0;
    systime_t stop = 0;
    systime_t delta = 0;
    systime_t current = 0;
    systime_t limit = 0;
    float delta_time = 0;

  //abbassa il pin
    palClearPad(T_PORT,T_PIN);
    chThdSleepMicroseconds(2);
  //registra il tempo di inizio
    start = chVTGetSystemTime();
    limit = chVTGetSystemTime() + 1000000;
  //Lancia il trigger
    palSetPad(T_PORT,T_PIN);
    chThdSleepMicroseconds(10);
    palClearPad(T_PORT,T_PIN);

  //LETTURA DEL TEMPO DI VOLO

    //verifica se il pin di input è alto (caso anomalo)
    if (palReadPad(E_PORT,E_PIN)==PAL_HIGH) {
      //c'è qualcosa che non va restituisce un errore
      return -99999.0;
    }
    else
    {
      //attende finquando non diventa positivo
      while (palReadPad(E_PORT,E_PIN)==PAL_LOW){
        //gestisce il tempo limite per il break
        current = chVTGetSystemTime();
        if (current>limit){
          //se si verifica il supermaneto del tempo limite restituisce 0
          return 0.0;
        }
      }
      //fine attesa
      stop = chVTGetSystemTime();
    }

  //calcola la differenza in tik
    delta = stop - start;

  //calcola il tempo in msec
    delta_time = delta;

    chprintf(chp, "%d\t", start);
    chprintf(chp, "%d\t", stop);
    chprintf(chp, "%d\t", delta);
    chprintf(chp, "\n\r", "");

  //resituisce il tempo
    return delta_time;
}



i try to print my start, stop and delta time, but i recive always the same number!

Can you illustrate you code??

Thanks

[SOLVED] Set the EXT for HC-SR04

Posted: Wed Sep 16, 2015 8:42 pm
by giannir1988
Finally the problem is resolved! :mrgreen: :mrgreen: :mrgreen:

I doesn't know the Echo system of the sensor HC-SR04.

This is the very simple function:

Code: Select all

/*-----------------------------------------------------------
 *  LIBRERIA PER L'UTILIZZO DEL SENSORE AD ULTRASUONI
 ----------------------------------------------------------*/

  //Definisce i pin di montaggio sensori
      #define T_PORT GPIOA
      #define T_PIN GPIOA_PIN10
      #define E_PORT GPIOB
      #define E_PIN GPIOB_PIN5
/*-------------------------------
 * DEFINIZIONE DEI PARAMETRI
 * ------------------------------ */


//PROCEDURA DI INIZIALIZZAZIONE
void usInit(void){

  //Definizione delle modalità di ogni pin
  palSetPadMode(T_PORT, T_PIN, PAL_MODE_OUTPUT_PUSHPULL);
  palSetPadMode(E_PORT, E_PIN, PAL_MODE_INPUT_PULLDOWN);

}

//PROCEDURA PER LA LETTURA DEL TEMPO DI PERCORRENZA
float read_time_distance(void){

  /*---------------------------------------------------------------------------
   * Come è fato il sensore HC-SR04:
   * Il sensore riceve in ingersso un impulsto della durata pari a
   * 10 microsecondi nel pin nominato Triger.
   * Una volta ricevuto il comando, il sensore invia un treno di impulsi,
   * tramite il piezo segnato come T.
   * Il Sensore, riceve dopo un tempo t il ritorno, sul piexo segnato come R.
   * Il sensore, internamente rileva questo tempo con un timer interno.
   * Alla fine della misurazione il sensore invia un impulso sul pin Echo di
   * durata pari proprio al tempo t.
   * La libreria non dovrà fare altro che rilevare la durata dell'impulso Echo
   * inviato dal sensore.
   * Bisognerà ovviamente gestire i casi di breakdown, nel caso in cui
   * l'impulso non arrivi o non termini (per colpa di una peridita di segnale
   * o un corto.
   --------------------------------------------------------------------------*/

  //definizione delle variabii
    systime_t start = 0;
    systime_t stop = 0;
    systime_t delta = 0;
    systime_t current = 0;
    systime_t limit = 0;
    float delta_time = 0;

  //resetta il Trigger
    palClearPad(T_PORT,T_PIN);
    chThdSleepMicroseconds(2);

  //Lancia il trigger
    palSetPad(T_PORT,T_PIN);
    chThdSleepMicroseconds(10);
    palClearPad(T_PORT,T_PIN);

  //definisce un limite entro il quale deve dare il return
    limit = chVTGetSystemTime() + MS2RTC(1000000,1000);

  //Attende che inizi l'impulso Echo
    while (palReadPad(E_PORT,E_PIN)==PAL_LOW){
        current = chVTGetSystemTime();
        if (current>limit){
          return 0.0;
        }
    }

  //registra il valore di di inizio dell'echo
    start = chVTGetSystemTime();
  //definsce il nuovo limite
    limit = start + MS2RTC(1000000,1000);

  //Attende che termini l'impulso Echo
    while (palReadPad(E_PORT,E_PIN)==PAL_HIGH){
      current = chVTGetSystemTime();
        if (current>limit){
          return 0.0;
        }
    }

    //registra il valore di fine impulso echo
      stop = chVTGetSystemTime();

    //ne determina la differenza
      delta = stop - start;

    //ritorna il valore
      return (float)delta;

}

/*--------------------------------------------------
 *  FUNZIONE PER CONVERITIRE IL TEMPO IN DISTANZA
 -------------------------------------------------*/
float take_distance_cm(float tempo_percorrenza){

   return ((0.03438 * tempo_percorrenza) / 2.0);

}


PS: i return the delta value because the param : #define CH_CFG_ST_FREQUENCY 1000000
in this way 1 Tik = 1 Microsecond

Re: Set the EXT for HC-SR04

Posted: Thu Sep 17, 2015 5:45 pm
by alex31
you are doing active wait, it is consuming to of cpu resources ...

I have to isolate my code from the projet from it comes to let it be autonomous, and i post it here.

Alexandre

Re: Set the EXT for HC-SR04

Posted: Thu Sep 17, 2015 6:01 pm
by alex31
the module sr04.h

Code: Select all

#pragma once                                                                                                                                                      
                                                                                                                                                                 
#include "ch.h"                                                                                                                                                   
#ifdef __cplusplus                                                                                                                                               
extern "C" {                                                                                                                                                     
#endif                                                                                                                                                           
                                                                                                                                                                 
  typedef struct   {                                                                                                                                             
    PWMDriver     *driver;                                                                                                                                       
    uint32_t      channel;                                                                                                                                       
    GPIO_TypeDef  *gpio;                                                                                                                                         
    uint32_t      pin;                                                                                                                                           
    uint8_t     alt;                                                                                                                                             
  } SonarGen ;                                                                                                                                                   
                                                                                                                                                                 
  typedef struct   {                                                                                                                                             
    ICUDriver     *driver;                                                                                                                                       
    uint32_t      channel;                                                                                                                                       
    GPIO_TypeDef  *gpio;                                                                                                                                         
    uint32_t      pin;                                                                                                                                           
    uint8_t     alt;                                                                                                                                             
  } SonarInput;                                                                                                                                                   
                                                                                                                                                                 
                                                                                                                                                                 
  void     sonarInit (const SonarGen *pwmGen, const SonarInput *pwmInput) ;                                                                                       
  float    sonarGetDistanceInCm (void);                                                                                                                           
  uint32_t sonarGetPeriodInMilliseconds (void);                                                                                                                   
  bool_t   sonarGetValidity (void);                                                                                                                               
#ifdef __cplusplus                                                                                                                                               
}                                                                                                                                                                 
#endif                                                                                                                                                           





the implmementation sr04.c

Code: Select all

#include "ch.h"
#include "hal.h"
#include "stdutil.h"
#include "globalVar.h"
#include "sonar_sr04.h"



static  float           lastDistance= 0.0f;
static  uint32_t   lastPeriod= 0;
static  float      meanDistance = 0.0f;
static  bool_t      lastMeasureValid=false;

static  const SonarGen    *pwmGen;
static  const SonarInput  *pwmInput;




static void setPwmValue (const SonarGen *s, const uint32_t value);
static void icuwidthcb(ICUDriver *icup);
static void icuperiodcb(ICUDriver *icup);


void sonarInit (const SonarGen *_pwmGen, const SonarInput *_pwmInput)
{
  pwmGen = _pwmGen;
  pwmInput = _pwmInput;

  static PWMConfig pwmcfgTim = {
    200000,                                 /* 200 khz PWM clock frequency.   */
    20000,                                 /* Initial PWM period 0.1s   */
    NULL,                                   /* no callback on PWM counter reset */
    {
      {PWM_OUTPUT_ACTIVE_HIGH, NULL},
      {PWM_OUTPUT_DISABLED, NULL},
      {PWM_OUTPUT_DISABLED, NULL},
      {PWM_OUTPUT_DISABLED, NULL}
    },
    0,
    0
  };
 
  pwmStart(pwmGen->driver, &pwmcfgTim);
  palSetPadMode (pwmGen->gpio, pwmGen->pin, PAL_MODE_ALTERNATE(pwmGen->alt));
  setPwmValue (pwmGen, 2); // 10 µs pulse


  static ICUConfig icucfgTim = {
    ICU_INPUT_ACTIVE_HIGH,
    100000,                                    /* 100 khz ICU clock frequency.   */
    icuwidthcb,
    icuperiodcb,
    NULL,
    ICU_CHANNEL_1,
    0
  };
 
  icuStart(pwmInput->driver, &icucfgTim);
  palSetPadMode (pwmInput->gpio, pwmInput->pin, PAL_MODE_ALTERNATE(pwmInput->alt));
  icuEnable(pwmInput->driver);
}

bool_t sonarGetValidity (void)
{
  return  lastMeasureValid;
}

float sonarGetDistanceInCm (void)
{
  return  meanDistance;
}

uint32_t  sonarGetPeriodInMilliseconds (void)
{
  return lastPeriod/100;
}

/*
#                 _ __           _                    _                   
#                | '_ \         (_)                  | |                 
#                | |_) |  _ __   _   __   __   __ _  | |_     ___         
#                | .__/  | '__| | |  \ \ / /  / _` | | __|   / _ \       
#                | |     | |    | |   \ V /  | (_| | \ |_   |  __/       
#                |_|     |_|    |_|    \_/    \__,_|  \__|   \___|       
*/


static void setPwmValue (const SonarGen *s, const uint32_t value)
{
  pwmEnableChannel(s->driver, s->channel, PWM_FRACTION_TO_WIDTH(s->driver, 100, value));
}

static void icuwidthcb(ICUDriver *icup)
{
  const uint32_t lastWidth = icuGetWidth(icup);
  lastDistance =  lastWidth * (10.0e-6f * 34000.0f /2.0f);
 
  if ((lastDistance > 4.0f) && (lastDistance <= 400.0f)) {
    meanDistance = ((4.0f*meanDistance)+lastDistance)/5.0f;
    lastMeasureValid = true;
  } else {
    lastMeasureValid = false;
  }
}

static void icuperiodcb(ICUDriver *icup)
{
  lastPeriod = icuGetPeriod(icup);
}


and exemple of use

Code: Select all

const SonarGen sonarPwmGen =   {
  .driver = &PWMD2, .channel = 0, .gpio = GPIOA, .pin = GPIOA_PWM2_CH1, .alt=1 // A15
};
const SonarInput sonarPwmInput = {
  .driver = &ICUD1, .channel = ICU_CHANNEL_1, .gpio = GPIOA, .pin = GPIOA_ICU1_CH1, .alt=1, // A8
};

sonarInit(&sonarPwmGen, &sonarPwmInput);


chprintf (chp, "Distance = %.1f cm;; period = %d ms ;; OK=%s",
                 sonarGetDistanceInCm(), sonarGetPeriodInMilliseconds(),
                 sonarGetValidity() ? "OK" : "BAD");


hope it helps
Alexandre