HIDE NAV

I2C Control of a Pi-Pico from a Raspberry Pi

A demonstration of I2C communication between a single board computer (Raspberry Pi) and a microcontroller target (RP2040 Pi Pico).

RASPBERRY PI SIDE



main.c


#include <lgpio.h>
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>

#define I2C_PICO_ADDRESS 0x31
#define FLOATS_PER_PACKET 2

void i2c_send_floats(int i2c_handle, float* data);

int main(int argNum, char* args[]) {
	int chip_handle;
	int i2c_handle;

	puts("i2c com test");

	//INITIALIZATION
	chip_handle = lgGpiochipOpen(0);
	if(chip_handle < 0) {
		puts("Error in initialization, handle is invalid");
		return 0;
	}
	i2c_handle = lgI2cOpen(1, I2C_PICO_ADDRESS, 0);
	if( i2c_handle <= 0){
		puts("Error opening I2C Bus, handle is invalid");
		return 0;
	}
	if(argNum  < 3) {
		printf("correct syntax:\n   %s <on-delay-seconds> <off-delay-seconds>\n", args[0]);
		return 0;
	}

	float data[] = {atof(args[1]), atof(args[2])};
	printf("sending on_delay = %.6f   off_delay = %.6f\n", data[0], data[1]);
	i2c_send_floats(i2c_handle, data);

	return 0;
}


void i2c_send_floats(int i2c_handle, float* data) {
	unsigned int dataSize = sizeof(float)* FLOATS_PER_PACKET;
	lgI2cWriteDevice(i2c_handle,(char*)data, dataSize);
}

PICO SIDE



i2c-link.h


#include "pico/stdlib.h"
#include "hardware/i2c.h"

#define I2C_LINK_SDA_GP 16
#define I2C_LINK_SCL_GP 17
#define I2C_LINK_MODULE i2c0
#define I2C_SELF_ADDRESS 0x31
#define I2C_LINK_DATA_RATE 4000000

#define FLOATS_PER_PACKET 2

void i2c_link_init();
void i2c_link_read_floats_blocking(float data[FLOATS_PER_PACKET]);


i2c-link.c


#include "i2c-link.h"

void i2c_link_init(){
  gpio_pull_up(I2C_LINK_SDA_GP);
  gpio_pull_up(I2C_LINK_SCL_GP);
  i2c_init(I2C_LINK_MODULE, I2C_LINK_DATA_RATE);
  i2c_set_slave_mode(I2C_LINK_MODULE, true, I2C_SELF_ADDRESS);
  gpio_set_function(I2C_LINK_SDA_GP, GPIO_FUNC_I2C);
  gpio_set_function(I2C_LINK_SCL_GP, GPIO_FUNC_I2C);
}

void i2c_link_read_floats_blocking(float data[FLOATS_PER_PACKET]){
  float value;
  for(int i = 0; i < FLOATS_PER_PACKET; i++){
    uint8_t buffer[sizeof(float)];
    i2c_read_raw_blocking(I2C_LINK_MODULE, buffer, sizeof(float));
    value = 0;
    for(int k = 0; k < sizeof(float); k++){
      *(int*)&value |= ((int)buffer[k] << (8*k));
    }
    data[i] = value;
  }
}


main.c



#include "pico/stdlib.h"
#include "i2c-link.h"
#define LED_ONB 25

bool led_onb_state = false;
int64_t led_on_micros = 50000;
int64_t led_off_micros = 50000;

int64_t alarm_callback_blink(alarm_id_t id, void *user_data);

int main() {
	// setup &  initialize
	i2c_link_init();
	float rx_buffer[FLOATS_PER_PACKET];
	//onboard led
	gpio_init(LED_ONB);
	gpio_set_dir(LED_ONB, GPIO_OUT);
	add_alarm_in_ms(1000, alarm_callback_blink, NULL, true);
	// primary loop
		while (true) {
			i2c_link_read_floats_blocking(rx_buffer);
			if(rx_buffer[0] >= 0.000005f){
				led_on_micros  = (int64_t) (rx_buffer[0] * 1e6f);
			} else led_on_micros = 5;
			if(rx_buffer[1] >= 0.000005f){
				led_off_micros = (int64_t) (rx_buffer[1] * 1e6f);
			} else led_off_micros = 5;
		}
	}

int64_t alarm_callback_blink(alarm_id_t id, void *user_data) {
	led_onb_state = !led_onb_state;
	gpio_put(LED_ONB, led_onb_state);
	if(led_onb_state == true)	return led_on_micros;
	else return led_off_micros;
}