Skip to content

Sensors and Stepper Motors

A comprehensive set of sensors, including photodiodes, IR sensors (IR LEDs and IR photodiodes), an ultrasound distance sensor, and an onboard accelerometer, equips the robots with advanced environmental perception capabilities.

ℹ️ Information Students are encouraged to utilize any model of sensor that meets the project requirements, connect them to the available pins on the PYNQ board and use the appropriate modules for data processing.

Guidance on sensor integration, specifically for the TCS3200 and VL53L0X sensors provided for the project, will be provided on this page.

⚠️ Warning > Ensure that the voltage levels of the sensors and outputs are compatible with the PYNQ board specifications (3.3V) to prevent any damage or malfunction

VL53L0X Distance Sensor

The VL53L0X sensor is a state-of-the-art time-of-flight laser-ranging module, crucial for precise distance measurement.

headers headers

Integration with PYNQ Board

  • The sensor interfaces with the PYNQ board via an interface PCB which routes I2C communication through specific pins designated for this purpose. This integration facilitates using the I2C protocol via the provided Arduino headers (AR SCL and AR SDA pins).
  • Detailed guidelines for interfacing and initializing the sensor, including pin mappings and specific connection instructions, are available here.
  • For efficient use of the sensor, it’s important to follow the specific settings and configuration presented on the sensor’s data sheet.
Practical Implementation Tips:
  • Ensure the wiring is correct: Vin to 3.3V, GND to GND, SCL to SCL, and SDA to SDA.
  • Use the provided libpynq I2C functions for seamless communication.
  • Consider implementing error handling to manage possible communication failures or data discrepancies.

TCS3200 Color Sensor

The TCS3200 is a sophisticated color sensor that utilizes a photodiode array to detect and measure color frequency.

headers

Integration with PYNQ Board

  • The sensor is connected with the PYNQ board through digital pins, utilizing pins S0 to S3 for frequency output scaling and color selection. This configuration allows for dynamic adjustments based on the sensor requirements.
  • Comprehensive information on the pin configuration and operational modes can be accessed through the sensor's data sheet
Practical Implementation Tips:
  • The primary task with the TCS3200 involves setting it up to output frequency on the OUT pin, which should be connected to a designated digital pin on the PYNQ board. The frequency measured from this output provides a direct correlation to the color intensity detected by the sensor.
  • To ensure that the color readings are accurate under varying light conditions, it is essential to calibrate the sensor. Calibration involves adjusting the scaling of the output frequency for different colors, based on predefined calibration procedures outlined in the Color Sensing Tutorial.

⚠️ Warning While initial setup and configuration are designed to be straightforward, the environmental conditions specific to Venus might require students to perform iterative testing and adjustments. This process is critical to ensure that the sensor accurately reflects the color properties of the samples under study.

Stepper Motors

The robots’ movement is controlled by high-precision stepper motors, selected for their accuracy and reliability in navigation, especially in challenging environments. A stepper motors does not rotate like a normal motor, but instead takes (many) small steps and when not moving it holds the current position. In the current setup to make one full rotation, you need to request 1600 steps:

// Initialize the stepper driver.
stepper_init();
// Apply power to the stepper motors.
stepper_enable();
// Move one full rotation.
stepper_steps(1600,1600);

The above code initializes the stepper driver, power on the stepper motors and makes the robot move with both wheels forward by one full wheel rotation. To move the robot backwards you specify a negative number. The maximum number of steps per command is 32767, ~20.5 rotations.

You can call stepper_steps while the robot is still moving, it will then continue with the next command directly after finishing the current.

It is also possible to change the speed of the wheel rotation, before requesting it to step you can you can set a speed per wheel:

stepper_set_speed(20000,20000);

The speed here is defined in time between each step, so the bigger the number, the slower the steps. The minimum is 3024 (~30uS per step, ~50ms per rotation) and the maximum is 65535 (655uS per step, ~1sec per rotation).

⚠️ Warning Be careful moving to quickly, the robot could easily topple over on start or stop.

Below is some sample code that listens on MQTT for a json formatted command and translates this into movement. It reports the current state back.

#include <arm_shared_memory_system.h>
#include <json-c/json.h>
#include <json-c/json_object.h>
#include <libpynq.h>
#include <platform.h>
#include <stdint.h>
#include <stepper.h>

void uart_read_array(const int uart, uint8_t *buf, uint8_t l) {
  for (uint8_t x = 0; x < l; x++) {
    buf[x] = uart_recv(uart);
  }
}

int main(void) {
  pynq_init();
  switchbox_set_pin(IO_AR0, SWB_UART0_RX);
  switchbox_set_pin(IO_AR1, SWB_UART0_TX);
  gpio_set_direction(IO_AR2, GPIO_DIR_INPUT);
  gpio_set_direction(IO_AR3, GPIO_DIR_INPUT);
  printf("AR2: %d\n", gpio_get_level(IO_AR2));
  printf("AR3: %d\n", gpio_get_level(IO_AR3));

  uart_init(UART0);

  uart_reset_fifos(UART0);

  stepper_init();

  stepper_enable();

  stepper_set_speed(1000, 1000);

  stepper_steps(100, 100);



  while (1) {
    if (uart_has_data(UART0)) {
      uint32_t size = 0;
      uart_read_array(UART0, &size, 4);
      char array[size];
      uart_read_array(UART0, &array, size);
      printf("data: %.*s\n", size, array);

      json_tokener *tok = json_tokener_new();

      json_object *root = json_tokener_parse_ex(tok, array, size);
      if (root) {
        int16_t l = 0, r = 0;
        json_object *lo = json_object_object_get(root, "left");
        if (lo) {
          l = json_object_get_int(lo);
        }
        json_object *ro = json_object_object_get(root, "right");
        if (ro) {
          r = json_object_get_int(ro);
        }
        json_object *so = json_object_object_get(root, "lspeed");
        json_object *sor = json_object_object_get(root, "rspeed");
        if (so && sor) {
          uint16_t s = json_object_get_int(so);
          uint16_t sr= json_object_get_int(sor);
          stepper_set_speed(s, sr);
        }
        printf("%d %d\n", l, r);
        stepper_steps(l, r);
        json_object_put(root);
      }
      json_tokener_free(tok);
    }

    usleep(1 * 1000);
  }

  while (!stepper_steps_done())
    ;

  stepper_destroy();

  pynq_destroy();
  return EXIT_SUCCESS;
}

Example message:

{
  "left": -32000,
  "right": -32000,
  "rspeed": 16000,
  "lspeed": 16000
}

For more information see libpynq documentation and pynq user documentation.