RoadTest: RoadTest the Raspberry Pi 4 Model B (2GB)
Author: abiswas1993
Creation date:
Evaluation Type: Development Boards & Tools
Did you receive all parts the manufacturer stated would be included in the package?: True
What other parts do you consider comparable to this product?: I have tried different SBC for this project. Performance-wise, the Lattepanda Alpha is best given the high price point (~400$) but for the bucks, Raspi 4 is the best. Especially for projects that don't require intense processing and cheap IoT servers.
What were the biggest problems encountered?: Connecting my Raspi 4 with Bluetooth speaker was really problematic. I tried to connect but ultimately failed. I think there are some space there for the development team to improve. Other than that the performance was more than expected.
Detailed Review:
The Goal
I am working on a remote vehicle monitoring system. The system is based on multiple NodeMCU board. The boards are supposed to collect data and publish it to a remote computer( in this case Raspi 4). So, in this road test, I tried to build a communication system based on MQTT and Mosquitto broker for Raspi and NodeMCU. I have programmed the raspberry pi 4 as an MQTT broker and used a GUI based switch to control an RGB led which signifies data transfer between the boards and customized the program to display random color pattern or fixed color. So let us begin.
Steps
1) Setting up the Raspberry Pi 4
The standard setup process of the Raspberry pi is well documented on the Raspberry pi org. website. I followed the document steps to setup my Raspi 4 - Link.
2) Description of the Process
MQTT: MQTT stands for Message Queuing Telemetry Transport. It basically means it is a communication protocol for low bandwidth devices well suited for small scale IoT applications. A well-documented description can be found https://randomnerdtutorials.com/what-is-mqtt-and-how-it-works/
Figure 1: Basic functionality of MQTT
So We need MQTT to build communication between the producer (Fig.1 NodeMCU(Blue) and the consumer(Python application)). In this road test, the producer will be a python program running on the Raspi 4 and the consumer will be the Huzzah Feather esp8266. The MQTT running on the Raspi 4 will act as a broker between these two processes.
Now, in Raspi 4 we will first create a GUI based on HTML file. Flask a python micro framework that will turn the Raspi 4 into a web server. Now this application will connect the MQTT broker through a client class called Paho-MQTT, which will then update the topic in the MQTT system. A topic is a specific thread for a specific group of information.
3) Downloading and Installing Mosquitto Broker for MQTT protocol
I started with installing the Mosquitto Broker for MQTT and the command is -
We would need this IP address later to configure our main application.
Now few things to mention. As I have understood Mosquitto work as a broker program but in order to turn the Raspi 4 into a webserver we need appropriate program. In this case, I used Flask. Later on, I will need to connect all of these pieces together to publish data to a specific topic. In this step, I have installed Flask for Raspi. The commands are -
pi@raspberrypi ~ $ sudo pip install flask
Now as the Mosquitto broker and web server script is installed. We need a piece of code to connect our desired python program to MQTT. To server this purpose, I have installed Paho- MQTT.
The commands are as follows-
Now that all the required programs are ready the final two pieces- 1) Python app and 2) HTML code is required to sort of combine and build up successful communication. For this section, I have modified Rui Santos code - Link for my own application needs.
# # Created by Rui Santos Edited By Arindam Biswas # Complete project details: http://randomnerdtutorials.com # import paho.mqtt.client as mqtt from flask import Flask, render_template, request app = Flask(__name__) mqttc=mqtt.Client() mqttc.connect("localhost",1883,60) mqttc.loop_start() # Create a dictionary called pins to store the pin number, name, and pin state: pins = { 4 : {'name' : 'Random Color', 'board' : 'esp8266', 'topic' : 'esp8266/4', 'state' : 'False'}, 5 : {'name' : 'Single Color', 'board' : 'esp8266', 'topic' : 'esp8266/5', 'state' : 'False'} } # Put the pin dictionary into the template data dictionary: templateData = { 'pins' : pins } @app.route("/") def main(): # Pass the template data into the template main.html and return it to the user return render_template('main.html', **templateData) # The function below is executed when someone requests a URL with the pin number and action in it: @app.route("/<board>/<changePin>/<action>") def action(board, changePin, action): # Convert the pin from the URL into an integer: changePin = int(changePin) # Get the device name for the pin being changed: devicePin = pins[changePin]['name'] # If the action part of the URL is "on," execute the code indented below: if action == "1" and board == 'esp8266': mqttc.publish(pins[changePin]['topic'],"1") pins[changePin]['state'] = 'True' if action == "0" and board == 'esp8266': mqttc.publish(pins[changePin]['topic'],"0") pins[changePin]['state'] = 'False' # Along with the pin dictionary, put the message into the template data dictionary: templateData = { 'pins' : pins } return render_template('main.html', **templateData) if __name__ == "__main__": app.run(host='0.0.0.0', port=8181, debug=True)
Finally, the HTML interface for controlling the LED -
<!DOCTYPE html> <head> <title>RPi RGB Control Web Server</title> <!-- Latest compiled and minified CSS --> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" integrity="sha384-1q8mTJOASx8j1Au+a5WDVnPi2lkFfwwEAa8hDDdjZlpLegxhjVME1fgjWPGmkzs7" crossorigin="anonymous"> <!-- Optional theme --> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap-theme.min.css" integrity="sha384-fLW2N01lMqjakBkx3l/M9EahuwpSfeNvV63J5ezn3uZzapT0u7EYsXMjQV+0En5r" crossorigin="anonymous"> <!-- Latest compiled and minified JavaScript --> <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js" integrity="sha384-0mSbJDEHialfmuBBQP6A4Qrprq5OVfW37PRR3j5ELqxss1yVqOtnepnHVP9aJ7xS" crossorigin="anonymous"></script> <meta name="viewport" content="width=device-width, initial-scale=1"> </head> <body> <h1>RPi Web Server - ESP8266 MQTT</h1> {% for pin in pins %} <h2>{{ pins[pin].name }} {% if pins[pin].state == 'True' %} is currently <strong>on</strong></h2><div><div> <a href="/esp8266/{{pin}}/0" role="button">Turn off</a></div></div> {% else %} is currently <strong>off</strong></h2><div><div> <a href="/esp8266/{{pin}}/1" role="button">Turn on</a></div></div> {% endif %} {% endfor %} </body> </html>
Now before running the application on Raspi, I have programmed the NodeMCU to blink an RGB LED. The Pin diagram of RGB LEDs common anode or common cathode can be seen in the following picture-
The RGB LED I used is a Common Cathode one. The circuit connection can be seen in the below diagram-
Initially, I have written a code to blink random colors with the adafruit Huzza )later this code will be used for blinking specific color or random color while button clicked on a raspi HTML interface). The code is as follows-
int redPin = 4; int greenPin = 12; int bluePin = 14; static int Red = 1, Green = 2, Blue = 3; int colR = 0, colG = 0, colB = 0; void setup() { Serial.begin(115200); pinMode(redPin, OUTPUT); pinMode(greenPin, OUTPUT); pinMode(bluePin, OUTPUT); } void loop() { // colR=random(0,255); // colG=random(0,255); // colB=random(0,255); setColor(Red); // red setRandom(); delay(100); } void setColor(int color) { if (color == 1) { analogWrite(redPin, 255); analogWrite(greenPin, 0); analogWrite(bluePin, 0); } else if(color==2) { analogWrite(redPin, 0); analogWrite(greenPin, 255); analogWrite(bluePin, 0); } else if(color==3) { analogWrite(redPin, 0); analogWrite(greenPin, 0); analogWrite(bluePin, 255); } } void setRandom() { int del = 1; analogWrite(redPin, 0); analogWrite(greenPin, 0); analogWrite(bluePin, 0); for (int i = 0; i <= 255; i++) { analogWrite(redPin, i); delay(del); } for (int i = 0; i <= 255; i++) { analogWrite(greenPin, i); delay(del); } for (int i = 0; i <= 255; i++) { analogWrite(bluePin, i); delay(del); } for (int i = 0; i <= 255; i++) { analogWrite(redPin, (255 - i)); delay(del); } for (int i = 0; i <= 255; i++) { analogWrite(greenPin, (255 - i)); delay(del); } for (int i = 0; i <= 255; i++) { analogWrite(bluePin, (255 - i)); delay(del); } }
The RGB led test video is added below-
Now I went ahead and downloaded the MQTT broker for Adafruit Huzzah esp8266 and edited the basic code to run two LEDs. Since I had an RGB Led connected I used two pins (RED, and Green) as two individual LEDs. The code and video demonstration is given below-
/* Basic ESP8266 MQTT example This sketch demonstrates the capabilities of the pubsub library in combination with the ESP8266 board/library. It connects to an MQTT server then: - publishes "hello world" to the topic "outTopic" every two seconds - subscribes to the topic "inTopic", printing out any messages it receives. NB - it assumes the received payloads are strings not binary - If the first character of the topic "inTopic" is an 1, switch ON the ESP Led, else switch it off It will reconnect to the server if the connection is lost using a blocking reconnect function. See the 'mqtt_reconnect_nonblocking' example for how to achieve the same result without blocking the main loop. To install the ESP8266 board, (using Arduino 1.6.4+): - Add the following 3rd party board manager under "File -> Preferences -> Additional Boards Manager URLs": http://arduino.esp8266.com/stable/package_esp8266com_index.json - Open the "Tools -> Board -> Board Manager" and click install for the ESP8266" - Select your ESP8266 in "Tools -> Board" */ #include <ESP8266WiFi.h> #include <PubSubClient.h> // Update these with values suitable for your network. const char* ssid = "........"; const char* password = "........"; const char* mqtt_server = "broker.mqtt-dashboard.com"; WiFiClient espClient; PubSubClient client(espClient); long lastMsg = 0; char msg[50]; int value = 0; void setup_wifi() { delay(10); // We start by connecting to a WiFi network Serial.println(); Serial.print("Connecting to "); Serial.println(ssid); WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } randomSeed(micros()); Serial.println(""); Serial.println("WiFi connected"); Serial.println("IP address: "); Serial.println(WiFi.localIP()); } void callback(char* topic, byte* payload, unsigned int length) { Serial.print("Message arrived ["); Serial.print(topic); Serial.print("] "); for (int i = 0; i < length; i++) { Serial.print((char)payload[i]); } Serial.println(); // Switch on the LED if an 1 was received as first character if ((char)payload[0] == '1') { digitalWrite(BUILTIN_LED, LOW); // Turn the LED on (Note that LOW is the voltage level // but actually the LED is on; this is because // it is active low on the ESP-01) } else { digitalWrite(BUILTIN_LED, HIGH); // Turn the LED off by making the voltage HIGH } } void reconnect() { // Loop until we're reconnected while (!client.connected()) { Serial.print("Attempting MQTT connection..."); // Create a random client ID String clientId = "ESP8266Client-"; clientId += String(random(0xffff), HEX); // Attempt to connect if (client.connect(clientId.c_str())) { Serial.println("connected"); // Once connected, publish an announcement... client.publish("outTopic", "hello world"); // ... and resubscribe client.subscribe("inTopic"); } else { Serial.print("failed, rc="); Serial.print(client.state()); Serial.println(" try again in 5 seconds"); // Wait 5 seconds before retrying delay(5000); } } } void setup() { pinMode(BUILTIN_LED, OUTPUT); // Initialize the BUILTIN_LED pin as an output Serial.begin(115200); setup_wifi(); client.setServer(mqtt_server, 1883); client.setCallback(callback); } void loop() { if (!client.connected()) { reconnect(); } client.loop(); long now = millis(); if (now - lastMsg > 2000) { lastMsg = now; ++value; snprintf (msg, 50, "hello world #%ld", value); Serial.print("Publish message: "); Serial.println(msg); client.publish("outTopic", msg); } }
Video Demonstration of the Basic two led code-
Since I have the two led version working I went ahead and added my code in which I modified the HTML interface in Raspi to show two buttons 1) Single Random Color or 2) Random color display and also modified the Adafruit Huzzah's MQTT code to 1) Display Random single color if button one is clicked or 2) Display Random color for a second if button two is pressed-
/***** All the resources for this project: https://randomnerdtutorials.com/ *****/ int redPin = 4; int greenPin = 12; int bluePin = 14; static int Red = 1, Green = 2, Blue = 3; //uncomment this line if using a Common Anode LED //#define COMMON_ANODE int colR = 0, colG = 0, colB = 0; // Loading the ESP8266WiFi library and the PubSubClient library #include <ESP8266WiFi.h> #include <PubSubClient.h> // Change the credentials below, so your ESP8266 connects to your router const char* ssid = "Ad-2-246"; const char* password = ""; // Change the variable to your Raspberry Pi IP address, so it connects to your MQTT broker const char* mqtt_server = ""; ///Erased please generate your own // Initializes the espClient WiFiClient espClient; PubSubClient client(espClient); // Connect an LED to each GPIO of your ESP8266 const int ledGPIO5 = 5; const int ledGPIO4 = 4; // Don't change the function below. This functions connects your ESP8266 to your router void setup_wifi() { delay(10); // We start by connecting to a WiFi network Serial.println(); Serial.print("Connecting to "); Serial.println(ssid); WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println(""); Serial.print("WiFi connected - ESP IP address: "); Serial.println(WiFi.localIP()); } // This functions is executed when some device publishes a message to a topic that your ESP8266 is subscribed to // Change the function below to add logic to your program, so when a device publishes a message to a topic that // your ESP8266 is subscribed you can actually do something void callback(String topic, byte* message, unsigned int length) { Serial.print("Message arrived on topic: "); Serial.print(topic); Serial.print(". Message: "); String messageTemp; for (int i = 0; i < length; i++) { Serial.print((char)message[i]); messageTemp += (char)message[i]; } Serial.println(); // Feel free to add more if statements to control more GPIOs with MQTT // If a message is received on the topic home/office/esp1/gpio2, you check if the message is either 1 or 0. Turns the ESP GPIO according to the message if(topic=="esp8266/4"){ Serial.print("Changing GPIO 4 to "); if(messageTemp == "1"){ setRandom(); Serial.print("On"); } else if(messageTemp == "0"){ //digitalWrite(ledGPIO4, LOW); Serial.print("Off"); } } if(topic=="esp8266/5"){ Serial.print("Changing GPIO 5 to "); if(messageTemp == "1"){ setColor(random(1,4)); Serial.print("On"); } else if(messageTemp == "0"){ //digitalWrite(ledGPIO5, LOW); setColor(random(1,4)); Serial.print("Off"); } } Serial.println(); } // This functions reconnects your ESP8266 to your MQTT broker // Change the function below if you want to subscribe to more topics with your ESP8266 void reconnect() { // Loop until we're reconnected while (!client.connected()) { Serial.print("Attempting MQTT connection..."); // Attempt to connect /* YOU NEED TO CHANGE THIS NEXT LINE, IF YOU'RE HAVING PROBLEMS WITH MQTT MULTIPLE CONNECTIONS To change the ESP device ID, you will have to give a unique name to the ESP8266. Here's how it looks like now: if (client.connect("ESP8266Client")) { If you want more devices connected to the MQTT broker, you can do it like this: if (client.connect("ESPOffice")) { Then, for the other ESP: if (client.connect("ESPGarage")) { That should solve your MQTT multiple connections problem THE SECTION IN loop() function should match your device name */ if (client.connect("ESP8266Client")) { Serial.println("connected"); // Subscribe or resubscribe to a topic // You can subscribe to more topics (to control more LEDs in this example) client.subscribe("esp8266/4"); client.subscribe("esp8266/5"); } else { Serial.print("failed, rc="); Serial.print(client.state()); Serial.println(" try again in 5 seconds"); // Wait 5 seconds before retrying delay(5000); } } } // The setup function sets your ESP GPIOs to Outputs, starts the serial communication at a baud rate of 115200 // Sets your mqtt broker and sets the callback function // The callback function is what receives messages and actually controls the LEDs void setup() { pinMode(redPin, OUTPUT); pinMode(greenPin, OUTPUT); pinMode(bluePin, OUTPUT); Serial.begin(115200); setup_wifi(); client.setServer(mqtt_server, 1883); client.setCallback(callback); } // For this project, you don't need to change anything in the loop function. // Basically it ensures that you ESP is connected to your broker void loop() { if (!client.connected()) { reconnect(); } if(!client.loop()) /* YOU NEED TO CHANGE THIS NEXT LINE, IF YOU'RE HAVING PROBLEMS WITH MQTT MULTIPLE CONNECTIONS To change the ESP device ID, you will have to give a unique name to the ESP8266. Here's how it looks like now: client.connect("ESP8266Client"); If you want more devices connected to the MQTT broker, you can do it like this: client.connect("ESPOffice"); Then, for the other ESP: client.connect("ESPGarage"); That should solve your MQTT multiple connections problem THE SECTION IN recionnect() function should match your device name */ client.connect("ESP8266Client"); } ///////////// void setColor(int color) { if (color == 1) { analogWrite(redPin, 255); analogWrite(greenPin, 0); analogWrite(bluePin, 0); } else if(color==2) { analogWrite(redPin, 0); analogWrite(greenPin, 255); analogWrite(bluePin, 0); } else if(color==3) { analogWrite(redPin, 0); analogWrite(greenPin, 0); analogWrite(bluePin, 255); } } void setRandom() { int del = 1; analogWrite(redPin, 0); analogWrite(greenPin, 0); analogWrite(bluePin, 0); for (int i = 0; i <= 255; i++) { analogWrite(redPin, i); delay(del); } for (int i = 0; i <= 255; i++) { analogWrite(greenPin, i); delay(del); } for (int i = 0; i <= 255; i++) { analogWrite(bluePin, i); delay(del); } for (int i = 0; i <= 255; i++) { analogWrite(redPin, (255 - i)); delay(del); } for (int i = 0; i <= 255; i++) { analogWrite(greenPin, (255 - i)); delay(del); } for (int i = 0; i <= 255; i++) { analogWrite(bluePin, (255 - i)); delay(del); } }
Conclusion:
It's fairly simple to code a Raspberry Pi 4 to act as a server. It's a really easy way to develop a GUI based IoT application. In my code,f I have edited specific part of the NodeMCU code which can be modified as users needs.