Skip to main content
gl2
Associate III
July 7, 2015
Question

How use ICU driver?

  • July 7, 2015
  • 7 replies
  • 2293 views
Posted on July 07, 2015 at 20:22

Hello,

I have to simulate the behavior of this function Arduino on Chibios for the management of my sensor.

duration = pulseIn(ECHO_PIN,HIGH);

I use ICU driver to detect the rising and falling edge. This is the Arduino code:

/*
Tested with HY-SRF05, HC-SR04
Assuming a room temp of 20 degrees centigrade
The circuit:
* VVC connection of the sensor attached to +5V
* GND connection of the sensor attached to ground
* TRIG connection of the sensor attached to digital pin 12
* ECHO connection of the sensor attached to digital pin 13
*/
const
int
TRIG_PIN = 12;
const
int
ECHO_PIN = 13;
void
setup() {
// initialize serial communication:
Serial.begin(9600);
pinMode(TRIG_PIN,OUTPUT);
pinMode(ECHO_PIN,INPUT);
}
void
loop()
{
long
duration, distanceCm, distanceIn;
// Give a short LOW pulse beforehand to ensure a clean HIGH pulse:
digitalWrite(TRIG_PIN, LOW);
delayMicroseconds(2);
digitalWrite(TRIG_PIN, HIGH);
delayMicroseconds(10);
digitalWrite(TRIG_PIN, LOW);
duration = pulseIn(ECHO_PIN,HIGH);
// convert the time into a distance
distanceCm = duration / 1 / 2 ;
distanceIn = duration / 74 / 2;
if
(distanceCm <= 0){
Serial.println(
''Out of range''
);
}
else
{
Serial.print(distanceIn);
Serial.print(
''in, ''
);
Serial.print(distanceCm);
Serial.print(
''cm''
);
Serial.println();
}
delay(1000);
}

This is the code that I wrote, but something is wrong:

/*
ChibiOS/RT - Copyright (C) 2006-2014 Giovanni Di Sirio
Licensed under the Apache License, Version 2.0 (the ''License'');
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an ''AS IS'' BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/* Inclusion of the main header files of all the imported components in the
order specified in the application wizard. The file is generated
automatically.*/
#include ''components.h''
#include ''icu_lld_cfg.h''
icucnt_t last_width, last_period;
void
icuwidthcb(ICUDriver *icup) {
palSetPad(PORT_A, Led_D12);
last_width = icuGetWidth(icup);
}
void
icuperiodcb(ICUDriver *icup) {
palClearPad(PORT_A, Led_D12);
last_period = icuGetPeriod(icup);
}
/*
* LEDs blinker thread, times are in milliseconds.
*/
static
WORKING_AREA(waThread1, 128);
static
msg_t Thread1(
void
*arg) {
(
void
)arg;
chRegSetThreadName(
''detection''
);
while
(TRUE) {
uint32_t duration, distanceCm;
SIU.PCR[3].R = 0b0100010100000100; 
/* PA3 alternate function. */
SIU.PCR[58].R = 0b0100010100000100; 
/* PD10 alternate function. */
palClearPad(PORT_A, TRIG_PIN); 
// low
osalThreadSleepMicroseconds(2);
palSetPad(PORT_A, TRIG_PIN); 
//high
osalThreadSleepMicroseconds(10);
palClearPad(PORT_A, TRIG_PIN); 
// low
palTogglePad(PORT_A,Led_D12);
icuStart(&ICUD4, &icu_config_icucfg);
icuEnable(&ICUD4);
palSetPad(PORT_A, ECHO_PIN); 
//high
icuwidthcb(&ICUD4);
icuperiodcb(&ICUD4);
duration = last_width;
chprintf((BaseSequentialStream *)&SD1,
''Input Capture 3 Value is %u, %u\r\n''
, last_width, last_period);
// convert the time into a distance
distanceCm = duration / 1 / 2 ;
chprintf((BaseSequentialStream *)&SD1,
''Distance cm: %u\r\n''
, distanceCm);
icuDisable(&ICUD4);
icuStop(&ICUD4);
osalThreadSleepMilliseconds(2000);
//chnWriteTimeout(&SD1, (uint8_t *)''%u\r\n'', 14, TIME_INFINITE);
//chprintf((BaseSequentialStream *)&SD1, ''%u'', duration);
osalThreadSleepMilliseconds(500);
}
return
0;
}
/*
* Application entry point.
*/
int
main(
void
) {
/* Initialization of all the imported components in the order specified in
the application wizard. The function is generated automatically.*/
componentsInit();
/*
* Activates the serial driver 1 using the driver default configuration.
*/
sdStart(&SD1, NULL);
/*
* Creates the detection thread.
*/
chThdCreateStatic(waThread1, 
sizeof
(waThread1), NORMALPRIO, Thread1, NULL);
chThdSleepMilliseconds(1000);
}

I am getting output as 1, 1 only. What have I missed? Are the callbacks? Should I read the time that the signal Echo go back. How can I do? Is the right way? Best regards Gianluca
    This topic has been closed for replies.

    7 replies

    Erwan YVIN
    ST Employee
    July 8, 2015
    Posted on July 08, 2015 at 10:21 Hello Gianluca , 1) First Problem :

    void
    icuwidthcb(ICUDriver *icup) {
    palSetPad(PORT_A, Led_D12);
    last_width = icuGetWidth(icup);
    }
    void
    icuperiodcb(ICUDriver *icup) {
    palClearPad(PORT_A, Led_D12);
    last_period = icuGetPeriod(icup);
    }

    are some callbacks called by interruption level and the callbacks should be in your configuration

    &icu_config_icucfg

    icuStart(&ICUD4, &icu_config_icucfg);

    you should remove in your main

    icuwidthcb(&ICUD4);
    icuperiodcb(&ICUD4);

    2) 2nd Problem :

    chprintf((BaseSequentialStream *)&SD1,

    ''Input Capture 3 Value is %u, %u
    
    ''

    , last_width, last_period);

    PulseIn in Arduino-Style is a blocking function Reads a pulse (either HIGH or LOW) on a pin. For example, if value is HIGH, pulseIn() waits for the pin to go HIGH, starts timing, then waits for the pin to go LOWand stops timing. Returns the length of the pulse in microseconds.Gives up and returns 0 if no pulse starts within a specified time out. Your log is too fast : you should wait some times before logging or log your pulse at Interruption level Tomorrow , i will bring my HC-SR04 and try to plug on SPC560D Discovery Board Best regards Erwan
    gl2
    gl2Author
    Associate III
    July 8, 2015
    Posted on July 08, 2015 at 12:30

    Hello Erwan,

    Thanks for your time. I have removed from my main:

    icuwidthcb (&ICUD4);
    icuperiodcb (&ICUD4);

    Then I added osalThreadSleepMilliseconds (2000); after icuEnable (& ICUD4);

    palClearPad(PORT_A, TRIG_PIN); 
    // low
    osalThreadSleepMicroseconds(2);
    palSetPad(PORT_A, TRIG_PIN); 
    //high
    osalThreadSleepMicroseconds(10);
    palClearPad(PORT_A, TRIG_PIN); 
    // low
    palTogglePad(PORT_A,Led_D12);
    icuStart(&ICUD4, &icu_config_icucfg);
    icuEnable(&ICUD4);
    osalThreadSleepMilliseconds(2000);
    palSetPad(PORT_A, ECHO_PIN); 
    //high
    icuDisable(&ICUD4);
    icuStop(&ICUD4);

    but still not working. It will definitely be something simple, but I'm a newcomer to embedded programming. Best regards Gianluca.
    Erwan YVIN
    ST Employee
    July 8, 2015
    Posted on July 08, 2015 at 13:57 Hello Gianluca , Could you confirm your board (HW) used (Pictus Discovery) ? i am checking your SIUL Configuration, do not hesitate to use Pinmap Wizard to configure your pins

    SIU.PCR[3].R = 0b0100010100000100; 
    /* PA3 alternate function. */
    SIU.PCR[58].R = 0b0100010100000100; 
    /* PD10 alternate function. */

    I will try with my sensor, tomorrow. Best regards Erwan
    gl2
    gl2Author
    Associate III
    July 8, 2015
    Posted on July 08, 2015 at 15:12

    Yes. My board is SPC560P-DISP. 144 pin.

    Yes the pinmap wizard is much better.

    Thanks.

    Best regards

    Gianluca.

    gl2
    gl2Author
    Associate III
    July 13, 2015
    Posted on July 13, 2015 at 17:44

    Hello Erwan,

    Have you new news?

    Best regards

    Gianluca.

    gl2
    gl2Author
    Associate III
    July 17, 2015
    Posted on July 17, 2015 at 10:07

    Hello,

    In company the advice they gave me was to write an interrupt routine.

    Best Regards

    Gianluca.

    Erwan YVIN
    ST Employee
    July 17, 2015
    Posted on July 17, 2015 at 11:32

    Hello Gianluca ,

    It is a good idea.

    you should measure the tick between the 2 interrupts in order to detect the duration ''like Pulsein''.

              Best Regards

                         Erwan