Flutter-Pi Codelab: Mastering GPIO, PWM, and I2C on Raspberry Pi

Sep 11, 2024

Werner Scholtz

final chips = FlutterGpiod.instance.chips;
for (final chip in chips) {
  print("chip name: ${chip.name}, chip label: ${chip.label}");
  for (final line in chip.lines) {
    print("  line: $line");
  }
}
chip name: gpiochip0, chip label: pinctrl-bcm2835
   line: GpioLine(info: LineInfo(name: 'ID_SDA', consumer: '', direction:  input, bias:  disable, isUsed: false, isRequested: false, isFree: true))
   line: GpioLine(info: LineInfo(name: 'ID_SCL', consumer: '', direction:  input, bias:  disable, isUsed: false, isRequested: false, isFree: true))
   line: GpioLine(info: LineInfo(name: 'GPIO2', consumer: '', direction:  input, bias:  disable, isUsed: false, isRequested: false, isFree: true))
   ...
   line: GpioLine(info: LineInfo(name: 'GPIO23', consumer: '', direction:  input, bias:  disable, isUsed: false, isRequested: false, isFree: true))
 chip name: gpiochip1, chip label: raspberrypi-exp-gpio
   line: GpioLine(info: LineInfo(name: 'BT_ON', consumer: 'shutdown', direction: output, bias:  disable, isUsed: true, isRequested: false, isFree: false))
   line: GpioLine(info: LineInfo(name: 'WL_ON', consumer: '', direction: output, bias:  disable, isUsed: false, isRequested: false, isFree: true))
   ...
/// The name of the GPIO chip that the LED is connected to.
const gpioChipName = 'gpiochip0';

/// The name of the GPIO line that the LED is connected to.
const ledGpioLineName = 'GPIO23';
/// The GPIO chip that the LED is connected to.
late final GpioChip _chip;

/// The GPIO line that the LED is connected to.
late final GpioLine _ledLine;

void initState() {
    super.initState();
    // Retrieve a list of GPIO chips attached to the system.
    final chips = FlutterGpiod.instance.chips;

    // Find the GPIO chip with the label _gpioChipLabel.
    _chip = chips.singleWhere((chip) {
       return chip.name == gpioChipName;
    });

    // Find the GPIO line with the name _ledGpioLineName.
    _ledLine = _chip.lines.singleWhere((line) {
       return line.info.name == ledGpioLineName;
    });
}
// Request control of the GPIO line as an output.
_ledLine.requestOutput(
  consumer: 'flutterpi_codelab',
  initialValue: false,
);
// Release control of the GPIO line.
_ledLine.release();
/// The state of the LED. (true = on, false = off)
bool _ledState = false;


Widget build(BuildContext context) {
  return Scaffold(
    appBar: AppBar(title: const Text('Flutter Pi Codelab')),
    body: ListView(
      children: <Widget>[
        SwitchListTile(
          title: const Text('LED Switch'),
          value: _ledState,
          onChanged: (value) {
            setState(() {
              // Update the state of the LED.
              _ledState = value;
            });

            // Set the value of the GPIO line to the new state.
            _ledLine.setValue(value);
          },
        ),
      ],
    ),
  );
}
void _updateLED(value) {
  setState(() {
    // Update the state of the LED.
    _ledState = value;
  });

  // Set the value of the GPIO line to the new state.
  _ledLine.setValue(value);
}
_ledLine?.requestOutput(
  consumer: 'flutterpi_codelab',
  initialValue: _ledState,
);
/// The name of the [GpioLine] that the button is connected to.
const buttonGpioLineName = 'GPIO24';
/// The GPIO line that the button is connected to.
late final GpioLine _buttonLine;
// Find the GPIO line with the name _buttonGpioLineName.
_buttonLine = _chip.lines.singleWhere((line) {
  return line.info.name == buttonGpioLineName;
});
// Rising means that the voltage on the line has risen from low to high.
SignalEdge.rising;

// Falling means that the voltage on the line has dropped from high to low.
SignalEdge.falling;
// Request control of the _buttonLine. (Because we are using the line as an input use the requestInput method.)
_buttonLine.requestInput(
  consumer: 'flutterpi_codelab',
  triggers: {
    SignalEdge.rising,
    SignalEdge.falling,
  },
);
_buttonLine.release();
// Listen for signal events on the _buttonLine.
_buttonLine.onEvent.listen(
  (event) => print(event),
);
signal event SignalEvent(edge: falling, timestamp: 0:37:03.476893, time: 2024-06-19 14:39:20.301019)
signal event SignalEvent(edge: rising, timestamp: 0:37:03.564660, time: 2024-06-19 14:39:20.388289)
signal event SignalEvent(edge: falling, timestamp: 0:37:04.507935, time: 2024-06-19 14:39:21.331576)
// Listen for signal events on the _buttonLine.
_buttonLine.onEvent.listen((event) {
  switch (event.edge) {
    case SignalEdge.rising:
      _updateLED(true);
    case SignalEdge.falling:
      _updateLED(false);
  }
});
dtoverlay=pwm,pin=18,func=2
SUBSYSTEM=="pwm*", PROGRAM="/bin/sh -c '\
        chown -R root:gpio /sys/class/pwm && chmod -R 770 /sys/class/pwm;\
        chown -R root:gpio /sys/devices/platform/soc/*.pwm/pwm/pwmchip* && chmod -R 770 /sys/devices/platform/soc/*.pwm/pwm/pwmchip*\
'"
git clone https://github.com/vsergeev/c-periphery.git
cd c-periphery
mkdir build
cd build
cmake -DBUILD_SHARED_LIBS=ON ..
make
sudo make install
// Set the libperiphery.so path
setCustomLibrary("/usr/local/lib/libperiphery.so");
/// The [PWM] chip number.
const pwmChip = 0;

/// The [PWM] channel number.
const pwmChannel = 0;
late final PWM _pwm;
_pwm = PWM(pwmChip, pwmChannel);
/// The period of the PWM signal in seconds.
final double _periodSeconds = 0.01;

/// The duty cycle, this is the amount of time the signal is high for the given period.
double _dutyCycle = 0.05; // 5%
// Set the period of the PWM signal.
_pwm.setPeriod(_periodSeconds);

// Set the duty cycle of the PWM signal.
_pwm.setDutyCycle(_dutyCycle);

// Enable the PWM signal.
_pwm.enable();
_pwm.dispose();
ListTile(
  title: const Text('PWM duty cycle'),
  subtitle: Slider(
    min: 0,
    max: 1,
    value: _dutyCycle,
    onChanged: (value) {
      setState(() {
        _dutyCycle = value;
      });

      _pwm.setDutyCycle(value);
    },
  ),
),
i2c-1   i2c             bcm2835 (i2c@7e804000)                  I2C adapter
0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:                         -- -- -- -- -- -- -- -- 
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
50: 50 -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
60: -- -- -- -- -- -- -- -- 68 -- -- -- -- -- -- -- 
70: -- -- -- -- -- -- -- --
/// The bus number of the rtc [I2C] device.
const int i2cBus = 1;
late final I2C _i2c;
late final DS1307 _rtc;
// Create a new I2C instance on bus 1.
_i2c = I2C(i2cBus);

// Create a new TinyRTC instance.
_rtc = DS1307(_i2c);
// Dispose of the I2C instance.
_i2c.dispose();

Widget build(BuildContext context) {
return Scaffold(
    appBar: AppBar(title: const Text('Flutter Pi Codelab')),
    body: ListView(
    children: <Widget>[
        ...
        RealTimeClockWidget(rtc: _rtc),
    ],
    ),
  );
}

Leave a Comment

Your Email address will not be published