Raspberry Piでリレーを制御する ~ 大光量のLEDを点灯する

Raspberry Pi上で動くプログラムで一番最初に紹介されるLED点滅プログラムですが、小さなLEDの点滅しかできません。それは、GPIOから提供される電流が極めて小さいからです。もし実用的なLED照明を作るには、どうすれば良いでしょうか。

いろいろ方法がありますが、今回はリレーを使ってみます。かねがね、スマートフォンから照明の点灯ができる仕組みを用意したいと思っていました。まだ先になりますが、自宅やキャンプ、車中泊などで、照明をスマートフォンから制御したいです。

そこで今回は、スマートフォンからRaspberry Pi (Zero)に信号を送り、Raspberry Piはリレーを制御してLEDを点灯、消灯します。

それでは、構成を紹介します。

(実際に組んだコードはもっと複雑で、抜粋して整形しているため、ミスがあるかもしれません。ご了承ください)

1.LED照明

白色LEDを3個、5Vで点灯させます。LEDは並列にします。そして必要な抵抗をオームの法則で計算すると33Ωとなります。実際に基板で作成したものが、上画像です。(使用した抵抗は80Ωです)

今回はテストなので、簡単な構成になっています。実用版は、12Vで駆動する、十分な明るさのあるLED照明を用意します。市販のものでも良いですね。

2.スマートフォン側プログラム

スマートフォン側のプログラムは、画面上にスイッチを配置してON/OFFします。そして、スイッチの変更を行ったタイミングで、UDPソケット通信を使い、Raspberry Piへ送信します。

送信データは文字列で、ONの場合"1″、OFFの場合"0″を送信します。Raspberry PiのIPアドレスを指定する必要があります。

レイアウト

    <EditText
        android:id="@+id/ipaddress"
        android:layout_width="200dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="24dp"
        android:cursorVisible="true"
        android:enabled="true"
        android:lines="1"
        android:maxLines="1"
        android:text="192.168.xxx.xxx"
        app:layout_constraintStart_toStartOf="parent"
        tools:layout_editor_absoluteY="16dp" />

    <Switch
        android:id="@+id/switch1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="24dp"
        android:layout_marginTop="32dp"
        android:text="Switch 1"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/ipaddress" />

ソース

public class MainActivity extends AppCompatActivity {
    private EditText IpAddressInput ;

    private final Handler handler = new Handler();

    private String wkstr ;
    private String clientIPAddress ;

    private int is_switch1 ;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        clientIPAddress = "192.168.XX.XXX" ;
        IpAddressInput = (EditText) findViewById(R.id.ipaddress) ;

        is_switch1 = 0 ;

        CompoundButton toggle1 = (CompoundButton) findViewById(R.id.switch1);

        toggle1.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                if (isChecked) {
                    is_switch1 = 1 ;
                } else {
                    is_switch1 = 0;
                }

                wkstr = format("%d", is_switch1);

                new Thread(new Runnable() {
                    @Override
                    public void run() {

                        try {

                            clientIPAddress = IpAddressInput.getText().toString() ;

                            DatagramSocket sendUdpSocket = new DatagramSocket();
                            InetAddress IPAddress = InetAddress.getByName(clientIPAddress);

                            byte[] strByte = wkstr.getBytes("UTF-8");

                            DatagramPacket sendPacket = new DatagramPacket(strByte, strByte.length, IPAddress, 60000);

                            sendUdpSocket.send(sendPacket);
                            sendUdpSocket.close();

                        } catch (IOException e) {

                            System.out.println(e.getMessage());
                        }
                    }
                }).start();

            }
        });

    }
}

3.Raspberry Pi側プログラム

Raspberry Pi側のプログラムは、Qtを使うフォームアプリケーションとします。フォームは、閉じるボタンが配置されているだけです。(本当は他にもあるのですが、今回の紹介では除いています)

リレーの仕組み

使用したリレーは、DC30V/10Aまで使える製品です。Raspberry Piとの接続は、5V端子とGND、そして任意のGPIOと接続します。GPIOの出力がON(3.3V)になれば、リレーもONになり、LEDへ電流が流れます。

今回、使用したGPIOは7番です。

(使用したリレーの端子が2か所壊れていました。高品質な日本製が良いでしょう)

リレーの動作側は、+配線をCOMとNOを経由するようにします。そしてリレーがONになると、COMとNOが繋がって電流が流れます。(購入したリレーのマニュアルが間違っています。注意してください)

ヘッダ

#define RELAY1 7

#define PORT_NUMBER 60000

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private slots:
    void udpupdate() ;
    void on_pushButton_clicked();

private:
    Ui::MainWindow *ui;

    QUdpSocket udpSocket;

    int relay1 ;

};

プログラム

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    udpSocket.bind( PORT_NUMBER );
    connect( &udpSocket, SIGNAL( readyRead() ),
             this, SLOT( udpupdate() ) );


    if ( wiringPiSetupGpio() == -1) {
        return ;
    }

    pinMode(RELAY1, OUTPUT);

    relay1 = 0 ;

    digitalWrite(RELAY1, 0);
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::udpupdate()
{

    QByteArray byteArray;

    byteArray.resize( udpSocket.pendingDatagramSize() );
    udpSocket.readDatagram( byteArray.data(), byteArray.size() );

    QString recieveStr = QString::fromUtf8(byteArray) ;

    relay1 = recieveStr.toInt() ;
    digitalWrite(RELAY1, relay1);

}

void MainWindow::on_pushButton_clicked()
{
    close() ;
}

4.動作結果

動作した様子が、一番最初の画像です。

スマートフォンでスイッチを操作することで、Raspberry Piに接続したリレーを通してLEDがON/OFFします。

個人的にはこれで良いのですが、Raspberry PiのIPアドレスを介することで一般的に使ってもらうには問題があります。やっぱりBluetoothでの操作が必要かも。M5Stack系を使ったLED照明のON/OFFも作りたいと思います。