Optocouplers, also known as opto-isolators, are electronic components that provide electrical isolation between two circuits by using light to transfer signals. Optocouplers are commonly used to protect sensitive electronic devices from voltage spikes, reduce noise and electromagnetic interference, and provide isolation in high-voltage applications.
Raspberry Pi Pico is a popular microcontroller board that features a powerful Arm Cortex-M0+ processor and a range of peripherals, including GPIOs, I2C, SPI, UART, and more. The Pico is an excellent platform for learning about microcontrollers and for developing a wide range of projects.
In this blog post, we will discuss how to interface an optocoupler to a Raspberry Pi Pico board. We will cover the basic theory behind optocouplers, the different types of optocouplers available, and how to connect an optocoupler to the Pico board.
Understanding Optocouplers Optocouplers are essentially a combination of a light-emitting diode (LED) and a photodetector. When a voltage is applied to the LED, it emits light, which is then detected by the photodetector. The photodetector then converts the light into an electrical signal, which is isolated from the input circuit.
Optocouplers are available in different configurations, including Darlington, triac, and transistor optocouplers. Each type of optocoupler has its own set of advantages and disadvantages, and the choice of optocoupler will depend on the specific application.
Connecting an Optocoupler to Raspberry Pi Pico To interface an optocoupler to a Raspberry Pi Pico board, we will use the transistor optocoupler configuration. This configuration is ideal for switching low-current DC loads, such as relays, LEDs, and motors.
The following steps will guide you on how to interface an optocoupler to a Raspberry Pi Pico board:
Step 1: Gather Components The following components are required for interfacing an optocoupler to a Raspberry Pi Pico board:
Transistor optocoupler (e.g., 4N35)
Resistor (e.g., 330 ohms)
Jumper wires
Breadboard (optional)
Step 2: Connect the Optocoupler to the Pico Board The following steps will guide you on how to connect the optocoupler to the Pico board:
Connect the VCC pin of the optocoupler to the 3.3V pin of the Pico board.
Connect the GND pin of the optocoupler to the GND pin of the Pico board.
Connect the Anode pin of the optocoupler to GPIO pin of the Pico board.
Connect the Cathode pin of the optocoupler to a 330-ohm resistor.
Connect the other end of the resistor to the GND pin of the Pico board.
This is a detailed project documentation for one of the videos we published on youtube. This is about making an IOT plant watering system using raspbery pi pico w
Components required
1) Raspberry Pi Pico W board
2) Relay
3)Usb Cable for program downloading
4) DC Power supply 5v and 12v
5)Water pump 5v
6) Plastic pipe for water distribution
7) Jumper wires
8) Breadboard
9)Small plastic jar for water storage
Circuit diagram for IOT Plant watering system using Rapsberry pi pico W
IOT Plant watering Circuit
Python Program for IOT Plant watering system using raspberry pi pico w
This is the BlynkLib.py, this is library code, use it as is without any changes/modifications
__version__ = "1.0.0"
import struct
import time
import sys
import os
try:
import machine
gettime = lambda: time.ticks_ms()
SOCK_TIMEOUT = 0
except ImportError:
const = lambda x: x
gettime = lambda: int(time.time() * 1000)
SOCK_TIMEOUT = 0.05
def dummy(*args):
pass
MSG_RSP = const(0)
MSG_LOGIN = const(2)
MSG_PING = const(6)
MSG_TWEET = const(12)
MSG_NOTIFY = const(14)
MSG_BRIDGE = const(15)
MSG_HW_SYNC = const(16)
MSG_INTERNAL = const(17)
MSG_PROPERTY = const(19)
MSG_HW = const(20)
MSG_HW_LOGIN = const(29)
MSG_EVENT_LOG = const(64)
MSG_REDIRECT = const(41) # TODO: not implemented
MSG_DBG_PRINT = const(55) # TODO: not implemented
STA_SUCCESS = const(200)
STA_INVALID_TOKEN = const(9)
DISCONNECTED = const(0)
CONNECTING = const(1)
CONNECTED = const(2)
print("""
___ __ __
/ _ )/ /_ _____ / /__
/ _ / / // / _ \\/ '_/
/____/_/\\_, /_//_/_/\\_\\
/___/ for Python v""" + __version__ + " (" + sys.platform + ")\n")
class EventEmitter:
def __init__(self):
self._cbks = {}
def on(self, evt, f=None):
if f:
self._cbks[evt] = f
else:
def D(f):
self._cbks[evt] = f
return f
return D
def emit(self, evt, *a, **kv):
if evt in self._cbks:
self._cbks[evt](*a, **kv)
class BlynkProtocol(EventEmitter):
def __init__(self, auth, tmpl_id=None, fw_ver=None, heartbeat=50, buffin=1024, log=None):
EventEmitter.__init__(self)
self.heartbeat = heartbeat*1000
self.buffin = buffin
self.log = log or dummy
self.auth = auth
self.tmpl_id = tmpl_id
self.fw_ver = fw_ver
self.state = DISCONNECTED
self.connect()
def virtual_write(self, pin, *val):
self._send(MSG_HW, 'vw', pin, *val)
def send_internal(self, pin, *val):
self._send(MSG_INTERNAL, pin, *val)
def set_property(self, pin, prop, *val):
self._send(MSG_PROPERTY, pin, prop, *val)
def sync_virtual(self, *pins):
self._send(MSG_HW_SYNC, 'vr', *pins)
def log_event(self, *val):
self._send(MSG_EVENT_LOG, *val)
def _send(self, cmd, *args, **kwargs):
if 'id' in kwargs:
id = kwargs.get('id')
else:
id = self.msg_id
self.msg_id += 1
if self.msg_id > 0xFFFF:
self.msg_id = 1
if cmd == MSG_RSP:
data = b''
dlen = args[0]
else:
data = ('\0'.join(map(str, args))).encode('utf8')
dlen = len(data)
self.log('<', cmd, id, '|', *args)
msg = struct.pack("!BHH", cmd, id, dlen) + data
self.lastSend = gettime()
self._write(msg)
def connect(self):
if self.state != DISCONNECTED: return
self.msg_id = 1
(self.lastRecv, self.lastSend, self.lastPing) = (gettime(), 0, 0)
self.bin = b""
self.state = CONNECTING
self._send(MSG_HW_LOGIN, self.auth)
def disconnect(self):
if self.state == DISCONNECTED: return
self.bin = b""
self.state = DISCONNECTED
self.emit('disconnected')
def process(self, data=None):
if not (self.state == CONNECTING or self.state == CONNECTED): return
now = gettime()
if now - self.lastRecv > self.heartbeat+(self.heartbeat//2):
return self.disconnect()
if (now - self.lastPing > self.heartbeat//10 and
(now - self.lastSend > self.heartbeat or
now - self.lastRecv > self.heartbeat)):
self._send(MSG_PING)
self.lastPing = now
if data != None and len(data):
self.bin += data
while True:
if len(self.bin) < 5:
break
cmd, i, dlen = struct.unpack("!BHH", self.bin[:5])
if i == 0: return self.disconnect()
self.lastRecv = now
if cmd == MSG_RSP:
self.bin = self.bin[5:]
self.log('>', cmd, i, '|', dlen)
if self.state == CONNECTING and i == 1:
if dlen == STA_SUCCESS:
self.state = CONNECTED
dt = now - self.lastSend
info = ['ver', __version__, 'h-beat', self.heartbeat//1000, 'buff-in', self.buffin, 'dev', sys.platform+'-py']
if self.tmpl_id:
info.extend(['tmpl', self.tmpl_id])
info.extend(['fw-type', self.tmpl_id])
if self.fw_ver:
info.extend(['fw', self.fw_ver])
self._send(MSG_INTERNAL, *info)
try:
self.emit('connected', ping=dt)
except TypeError:
self.emit('connected')
else:
if dlen == STA_INVALID_TOKEN:
self.emit("invalid_auth")
print("Invalid auth token")
return self.disconnect()
else:
if dlen >= self.buffin:
print("Cmd too big: ", dlen)
return self.disconnect()
if len(self.bin) < 5+dlen:
break
data = self.bin[5:5+dlen]
self.bin = self.bin[5+dlen:]
args = list(map(lambda x: x.decode('utf8'), data.split(b'\0')))
self.log('>', cmd, i, '|', ','.join(args))
if cmd == MSG_PING:
self._send(MSG_RSP, STA_SUCCESS, id=i)
elif cmd == MSG_HW or cmd == MSG_BRIDGE:
if args[0] == 'vw':
self.emit("V"+args[1], args[2:])
self.emit("V*", args[1], args[2:])
elif cmd == MSG_INTERNAL:
self.emit("internal:"+args[0], args[1:])
elif cmd == MSG_REDIRECT:
self.emit("redirect", args[0], int(args[1]))
else:
print("Unexpected command: ", cmd)
return self.disconnect()
import socket
class Blynk(BlynkProtocol):
def __init__(self, auth, **kwargs):
self.insecure = kwargs.pop('insecure', False)
self.server = kwargs.pop('server', 'blynk.cloud')
self.port = kwargs.pop('port', 80 if self.insecure else 443)
BlynkProtocol.__init__(self, auth, **kwargs)
self.on('redirect', self.redirect)
def redirect(self, server, port):
self.server = server
self.port = port
self.disconnect()
self.connect()
def connect(self):
print('Connecting to %s:%d...' % (self.server, self.port))
s = socket.socket()
s.connect(socket.getaddrinfo(self.server, self.port)[0][-1])
try:
s.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
except:
pass
if self.insecure:
self.conn = s
else:
try:
import ussl
ssl_context = ussl
except ImportError:
import ssl
ssl_context = ssl.create_default_context()
self.conn = ssl_context.wrap_socket(s, server_hostname=self.server)
try:
self.conn.settimeout(SOCK_TIMEOUT)
except:
s.settimeout(SOCK_TIMEOUT)
BlynkProtocol.connect(self)
def _write(self, data):
#print('<', data)
self.conn.write(data)
# TODO: handle disconnect
def run(self):
data = b''
try:
data = self.conn.read(self.buffin)
#print('>', data)
except KeyboardInterrupt:
raise
except socket.timeout:
# No data received, call process to send ping messages when needed
pass
except: # TODO: handle disconnect
return
self.process(data)
Below is the main code for running the project. You can modify it according to your needs about pins usage
import time
import network
from machine import Pin
import BlynkLib
wlan = network.WLAN(network.STA_IF)
wlan.active(True)
wlan.connect("Robotics Lab","Robotics@321")
BLYNK_AUTH = 'ozDgrBQOhQv0Hc-8z2oNHSIdscNyEHd6'
# Wait for network connection
wait = 10
while wait > 0:
if wlan.status() < 0 or wlan.status() >= 3:
break
wait -= 1
print('waiting for connection...')
time.sleep(1)
# Handle connection error
if wlan.status() != 3:
raise RuntimeError('network connection failed')
else:
print('connected')
ip = wlan.ifconfig()[0]
print('IP: ', ip)
# Connect to Blynk
blynk = BlynkLib.Blynk(BLYNK_AUTH)
# Initialize the relay pins
relay1_pin = Pin(1, Pin.OUT)
led_pin = Pin("LED", Pin.OUT)
# Register virtual pin handler
@blynk.on("V1") #virtual pin V1
def v1_write_handler(value): #read the value
if int(value[0]) == 1:
relay1_pin.value(1) #turn the relay1 on
else:
relay1_pin.value(0) #turn the relay1 off
@blynk.on("V2") #virtual pin V1
def v2_write_handler(value): #read the value
if int(value[0]) == 1:
led_pin.value(1) #turn the relay1 on
else:
led_pin.value(0) #turn the relay1 off
while True:
blynk.run()
Data Logger Using DS18B20 Temperature Sensor With Raspberry Pi
Introduction
In this tutorial we are going to learn how to make Data Logger with csv file extension by using DS18B20 Temperature Sensor With Raspberry Pi
Component Required
Raspberry Pi Board
Breadbord
Power supply
DS18B20 Temperature sensor
10 Kilo Ohm Resistor (pull up)
Breadbord
Connecting Wires
Circuit
Description
The DS18B20 is a precise digital temperature sensor known for its accuracy and simplicity. When combined with the Raspberry Pi, this sensor opens up a world of possibilities for temperature monitoring and control in various applications. In this process of interfacing the DS18B20 sensor with the Raspberry Pi, enabling you to measure temperature with ease
Steps
Step 1: Prepare the Raspberry Pi Ensure that your Raspberry Pi is up and running with a compatible operating system (such as Raspbian or Raspberry Pi OS). Make sure it is connected to a power source and accessible via SSH or a monitor and keyboard.
Step 2: Connect the DS18B20 Sensor Connect the DS18B20 sensor to the Raspberry Pi using the following steps:
Locate the three pins on the DS18B20 sensor: GND (ground), VCC (power supply), and DATA (data line).
Connect the GND pin to any available ground pin on the Raspberry Pi (e.g., Pin 6).
Connect the VCC pin to the 3.3V power supply pin on the Raspberry Pi (e.g., Pin 1).
Connect the DATA pin to an available GPIO pin on the Raspberry Pi (e.g., GPIO 4).
Finally, connect the 4.7kΩ resistor between the VCC and DATA pins of the sensor.
Step 2: Connect the DS18B20 Sensor Connect the DS18B20 sensor to the Raspberry Pi using the following steps:
Locate the three pins on the DS18B20 sensor: GND (ground), VCC (power supply), and DATA (data line).
Connect the GND pin to any available ground pin on the Raspberry Pi (e.g., Pin 6).
Connect the VCC pin to the 3.3V power supply pin on the Raspberry Pi (e.g., Pin 1).
Connect the DATA pin to an available GPIO pin on the Raspberry Pi (e.g., GPIO 4).
Finally, connect the 4.7kΩ resistor between the VCC and DATA pins of the sensor.
Step 3: Enable 1-Wire Interface To communicate with the DS18B20 sensor, we need to enable the 1-Wire interface on the Raspberry Pi. Follow these steps:
Open the terminal on your Raspberry Pi.
Type the following command and press Enter: sudo raspi-config
Use the arrow keys to navigate to “Interfacing Options” and press Enter.
Scroll down to “1-Wire” and press Enter.
Select “Yes” to enable the 1-Wire interface.
Reboot your Raspberry Pi by typing sudo reboot and pressing Enter.
Step 4: Identify the Sensor’s Unique ID After enabling the 1-Wire interface, we need to identify the unique ID of the DS18B20 sensor connected to the Raspberry Pi. Follow these steps:
Open the terminal on your Raspberry Pi.
Type the following command and press Enter: ls /sys/bus/w1/devices/
You should see a list of directories starting with “28-” followed by a unique ID. This ID represents your DS18B20 sensor.
Step 5: Read Temperature Data Now that we have the unique ID, we can read temperature data from the DS18B20 sensor. Use the following steps:
Open the terminal on your Raspberry Pi.
Type the following command, replacing <sensor_ID> with your sensor’s unique ID, and press Enter: cat /sys/bus/w1/devices/<sensor_ID>/w1_slave
The terminal will display the temperature reading in raw format. Look for the line that starts with “t=” followed by a temperature value in millidegrees Celsius.
Convert the millidegrees Celsius reading to a readable format (e.g., °C or °F) using the appropriate formula.
Code
import os
import glob
import time
import datetime
os.system('modprobe w1-gpio')
os.system('modprobe w1-therm')
base_dir = '/sys/bus/w1/devices/'
device_folder = glob.glob(base_dir + '28*')[0]
device_file = device_folder + '/w1_slave'
def read_temp_raw():
f = open(device_file, 'r')
lines = f.readlines()
f.close()
return lines
def read_temp():
lines = read_temp_raw()
while lines[0].strip()[-3:] != 'YES':
time.sleep(0.2)
lines = read_temp_raw()
equals_pos = lines[1].find('t=')
if equals_pos != -1:
temp_string = lines[1][equals_pos+2:]
temp_c = float(temp_string) / 1000.0
temp_f = temp_c * 9.0 / 5.0 + 32.0
return temp_c, temp_f
while True:
dtime = datetime.datetime.now()
mydate = str(dtime.date()) #get date in one variable, in text format
mytime = str(dtime.time()) #get time in one variable, in text format
a = read_temp() #get temperature value
print(a[0])
mylog = open('log.csv','a')
mystr = mydate + "," + mytime + "," + str(a[0]) + "\n"
#print(mystr)
mylog.write(mystr)
mylog.close()
time.sleep(1)
Photos
Youtube Working Video for Data Logger Using DS18B20 Temperature Sensor
This is a follow up post to this last one where we installed mysql on raspberry pi and added a remote user to it. If you haven’t done it, then please go here and do that first on raspberry pi
Add the MySQL Connector to Visual Studio
In order to use MySQL related code in your program, you need to add the default mysql connector to your project. Which is using MySql.Data.MySqlClient;
To do this, just right click your project and click on “Manage nuGET Packages”
manage nuget packages
Click on the Manage nuget packages link as shown in the yellow box in above Image. This will open the nuget package manager in visual studio. Here, simply search for Mysql and you’ll get the first result as the MySQL.Data by Oracle. That is the one we need to install
See the Image below
Click on the MySQl.Data and install that package, it should take about 2-5 minutes. Once done, you can run the next program to check the connection between C# code and mysql running on raspberry pi
.net code to connect to mysql on raspberry pi
Once everything is in place, just open your visual studio and create a console application. You need to use below code in console application to test your connection. Make sure to use the IP address, user name and password according to your particular instance. Just make sure to change this line in the code as per your raspberry pi address and userid and password of database and also the database name.
Run the console application. If it shows the version of the mariadb on console, it means your connection is working
using System;
using MySql.Data.MySqlClient;
namespace ConsoleApp_testMariadb
{
class Program
{
static void Main(string[] args)
{
string cs = @"server=192.168.0.133;userid=dfpl;password=dfpl;database=mts";
using var con = new MySqlConnection(cs);
con.Open();
Console.WriteLine($"MySQL version : {con.ServerVersion}");
con.Close();
}
}
}
While experimenting with mysql on Raspberry Pi, I often stumble upon few steps. Therefore I decided to write a post about creating the remote connection on mysql on raspberry pi. This post is about how to login to mysql on raspberry pi from windows computer. The steps are as they worked for me and may be different for you depending on version on your raspberry pi and your mariadb.
I have Raspberry Pi 4, 2GB RAM with the raspberry Pi os version February 2021
Mariadb on raspberry Pi Version : 10.3.27-MariaDB-0+deb10u1 |
How to connect to mariadb (free version of mysql) Server running on Raspberry Pi from Visual Studio Application
Install MySQL on Raspberry Pi
Since MySQL is a proprietary ORACLE product, there is no way you can install the MySQL on raspberry pi, however, we can use the free version of mysql which is called MariaDB on Raspberry Pi. Exactly the same functionality for all basic rdbms applications
Install Mariadb On Raspberry Pi
To install mariadb on raspberry Pi, run following series of commands. The update and upgrade are optional if you’ve recently done them on your raspberry Pi. So Open the terminal of Raspberry Pi, and use these commands to get mariadb installed on your raspberry pi
Allow remote connection to Mariadb On Raspberry Pi
By default, MySQL or Mariadb on raspberry pi is not configured to accept remote connections. You can enable remote connections by modifying the configuration file: For me, in the raspberry pi, the configuration file WAS NOT LOCATED on this address
sudo nano /etc/mysql/my.cnf
Instead I found it at
/etc/mysql/mariadb.conf.d/50-server.cnf
So you may need to experiment with your raspberry pi and the version of mariadb to see where you find this file
Here, find the bind-address line which should be currently pointing to localhost address which is 127.0.0.1. In order to login from external source, you’ll have 2 options.
To access from A specific computer ONLY, you need to put address of that computer
To access from Any computer on LAN, change this address to 0.0.0.0 In my case, I did this.
Now,
Restart the MySQL service
sudo service mysql restart
Setup MySQL permissions
Connect to your MySQL instance as root:
mysql -p -u root
Remember, you can’t access mysql remotely using root user, so don’t try with it and simply create a new user which should be created at both localhost and at ‘%’ just like below
Login to Mariadb on Raspberry Pi from Windows Computer
Now that we have created a user to login to our database remotely, its time to test this connection. To do this, you’ll need to install some database client on windows machine just like dbeaver
Once you install dbeaver, you can login to your database by specifying the server address as IP_OF_YOUR_RPI:3306
3306 is the default port number of mariadb server on raspberry pi and then you can see the data through dbeaver
mariadb on raspberry pi connection from windows pc
BMP180 is a nice tiny sensor which can give the values of
Atmospheric Pressure
Temperature
Altitude
In this video, we’ll see how we can interface Raspberry pi with BMP180 and how to write python code for the same.
In order to follow this video you’ll need
Raspberry Pi 2/3/4 with Raspbian OS Installed on it
BMP180 Sensor
Female to Female Wire connectors
For setting up the raspberry pi and start using it, you can follow this post.
How to interface I2C Sensor with Raspberry Pi
Python Program to interface raspberry pi with BMP180.
The video shows about 2 different programs one is the library package and other is testing code. Make sure while testing out, both the programs stay in the same folder.
import bmpsensor
import time
while True:
temp, pressure, altitude = bmpsensor.readBmp180()
print("Temperature is ",temp) # degC
print("Pressure is ",pressure) # Pressure in Pa
print("Altitude is ",altitude) # Altitude in meters
print("\n")
time.sleep(2)
If you face any issues with the code or working or explanation, feel free to comment about it!!