Pulse counting using ULP C macros does not work

lstrobel
Posts: 2
Joined: Wed Dec 11, 2024 6:36 pm

Pulse counting using ULP C macros does not work

Postby lstrobel » Wed Dec 11, 2024 6:55 pm

Hi together,
I try to count pulses on a RTC GPIO using C macros in a arduino sketch.
The main cpu gets the counted pulses from the RTC_SLOW_MEM[0] and prints it, prepares the ulp program, starts it and goes to deep sleep for a given time. After that time it restarts again.
So far so good.
What I would expect is, that I get the during sleep time counted pulses.
What I get is the sum of countet pulses over all sleep time periods. It seems that the initialization for the pulse counter does not work correctly.

Is anybody out there having an idea whats wrong with the picture?
Thanx
Lutz

Now the code, which is taken from https://github.com/Neurotech-Hub/ULP_Ex ... S3-Arduino.

Code: Select all

#include "esp32/ulp.h"
#include "driver/rtc_io.h"
#include "soc/rtc_io_reg.h"

#define GPIO_SENSOR_PIN GPIO_NUM_27  // GPIO pin connected to the sensor
#define RTC_GPIO_INDEX 17            // attain dynamically with: rtc_io_number_get(GPIO_SENSOR_PIN)

#define LED_PIN 13

enum {
  EDGE_COUNT,
  SLOW_PROG_ADDR  // Program start address
};

// counts all state changes (LOW->HIGH, HIGH->LOW)
// divide by 2 for single transition type
const ulp_insn_t ulp_program[] = {
  // Initialize transition counter and previous state
  I_MOVI(R2, 1),  // R2 <- 1 (previous state, assume HIGH initially)
  I_MOVI(R3, 0),  // R3 <- 0 (reset the transition counter)
 
  // Main loop
  M_LABEL(1),

 // Read Register RTCIO_RTC_GPIO_IN_REG (0x0024) +  RTC_GPIO_INDEX with RTC offset
  I_RD_REG(RTC_GPIO_IN_REG, RTC_GPIO_INDEX + RTC_GPIO_IN_NEXT_S, RTC_GPIO_INDEX + RTC_GPIO_IN_NEXT_S),

  // Save the current state in a temporary register (R1)
  I_MOVR(R1, R0),  // R1 <- R0 (store current GPIO state temporarily)

  // Compare current state (R1) with previous state (R2)
  I_SUBR(R0, R1, R2),  // R0 = current state (R1) - previous state (R2)
  I_BL(5, 1),          // ??? If R0 == 0 (no state change), skip instructions
                       // I_BL means branch if R0 < 1, not?
  I_ADDI(R3, R3, 1),   // Increment R3 by 1 (transition detected)
  I_MOVR(R2, R1),      // R2 <- R1 (store the current state for the next iteration)

  // Store the transition counter
  I_MOVI(R1, EDGE_COUNT),  // Set R1 to address RTC_SLOW_MEM[1]
  I_ST(R3, R1, 0),         // Store it in RTC_SLOW_MEM

  // RTC clock on the ESP32-S3 is 17.5MHz, delay 0xFFFF = 3.74 ms
  I_DELAY(0xFFFF),  // debounce
  I_DELAY(0xFFFF),  // debounce
  I_DELAY(0xFFFF),  // debounce
  I_DELAY(0xFFFF),  // debounce
  I_DELAY(0xFFFF),  // debounce
  I_DELAY(0xFFFF),  // debounce
 
  M_BX(1),  // Loop back to label 1
  I_HALT()
};

void init_ulp_program() {
  memset(RTC_SLOW_MEM, 0, CONFIG_ULP_COPROC_RESERVE_MEM);  // set to zeros, optional
  size_t size = sizeof(ulp_program) / sizeof(ulp_insn_t);
  esp_err_t err = ulp_process_macros_and_load(SLOW_PROG_ADDR, ulp_program, &size);  // offset by PROG_ADDR

  if (err == ESP_OK) {
    //Serial.println("ULP program loaded successfully."); // optional
  } else if (err == ESP_ERR_NO_MEM) {
    Serial.println("Error: Not enough memory to load ULP program.");
  } else {
    Serial.printf("Error: ULP program load returned unexpected error %d\n", err);
  }

  // init GPIO for ULP to monitor
  rtc_gpio_init(GPIO_SENSOR_PIN);
  rtc_gpio_set_direction(GPIO_SENSOR_PIN, RTC_GPIO_MODE_INPUT_ONLY);
  rtc_gpio_pullup_en(GPIO_SENSOR_PIN);     // enable the pull-up resistor
  rtc_gpio_pulldown_dis(GPIO_SENSOR_PIN);  // disable the pull-down resistor
  rtc_gpio_hold_en(GPIO_SENSOR_PIN);       // required to maintain pull-up
}

void setup() {
  pinMode(LED_PIN, OUTPUT);
  digitalWrite(LED_PIN, HIGH);  // turn on during init

  Serial.begin(115200);
  delay(1000);  // Connect delay

 
  // show count, will init to a random value
  Serial.printf("Count: %u\n", RTC_SLOW_MEM[EDGE_COUNT] & 0xFFFF);
 
  init_ulp_program();  // Load the ULP program

  esp_sleep_enable_timer_wakeup(10000 * 1000);  // Wake up every 10 seconds

  ulp_run(SLOW_PROG_ADDR);  // Start the ULP program with offset

  digitalWrite(LED_PIN, LOW);  // turn off during sleep

  esp_deep_sleep_start();  // Enter deep sleep
}

void loop() {
}

lstrobel
Posts: 2
Joined: Wed Dec 11, 2024 6:36 pm

Re: Pulse counting using ULP C macros does not work

Postby lstrobel » Thu Dec 12, 2024 8:26 pm

solved!

Code: Untitled.txt Select all


  // Store the transition counter
I_MOVI(R1, EDGE_COUNT), // Set R1 to address RTC_SLOW_MEM[1]
I_ST(R3, R1, 0), // Store it in RTC_SLOW_MEM
does not work, but ...

Code: Untitled.txt Select all


 I_MOVI(R1, EDGE_COUNT),  // Set R1 to address RTC_SLOW_MEM[1]
I_LD(R0, R1, 0),
I_ADDI(R0, R0, 1),
I_ST(R0, R1, 0),

... does

Who is online

Users browsing this forum: Amazon [Bot], Applebot, Barkrowler and 3 guests