14. Interface and Application Programming¶
This week’s Assignment¶
Group assignment:¶
- Compare as many tool options as possible.
- Document your work on the group work page and reflect on your individual page what you learned.
Individual assignment:¶
- Write an application for the embedded board that you made. that interfaces a user with an input and/or output device(s)
Learning outcomes:¶
- Implement a User Interface (UI) using programming and explore protocols to communicate with a microcontroller board that you designed and made.
Group Assignment¶
This week’s group work page is here
Individual Assignment¶
Processing¶
I made color select screen by Processing.
The color was first selected by Red, Green, or Blue button.
Then, it could be changed with slide potentiometers.
The color was select by pushing button and potentiometer and then also changed the background color.
First try¶
First aim was a screen with 3 button(red, green, blue).
When you touch one of the button, the background color is changed as the button color.
I wrote the code using the example “button” at Processing as a reference.
Note
In the example code, I didn’t understand about the equation below,
sqrt(sq(disX) + sq(disY)) < diameter/2
I asked chatGPT about it.
(1) First Mistake
When I wrote a code on the Processing, the screen was appeared only background color and no circle was there.
I asked chatGPT checking my code, and it told the order of description of circle and background should be opposite.
After switching the order, all circles were seen on the screen.
(2) Second Mistake
Then the circles are seen on the screen but the color didn’t change even pushing the button.
I asked again about the solution to chatGPT.
first wrong part -> no break in each case sentence
switch (currentButton){
case 0: currentColor = baseColor;
case 1: currentColor = RedOn;
case 2: currentColor = GreenOn;
case 3: currentColor = BlueOn;
default: currentColor = baseColor;
}
switch (currentButton){
case 0: currentColor = baseColor;
break;
case 1: currentColor = RedOn;
break;
case 2: currentColor = GreenOn;
break;
case 3: currentColor = BlueOn;
break;
default: currentColor = baseColor;
break;
}
I want to create a code that only changes the color of the background
to the chosen color when the button is pushed.
I see!
So you want to make the specification ‘The color doesn't change just
by hovering the mouse, but the background color only changes
when the button is clicked’.
In that case, in
✅ draw() you just draw the background color according to the current currentButton.
In ✅ mousePressed(), determine ‘which button is pressed’ from the mouse position
and update the currentButton only then.
Second Try¶
Then I’d like to put slide potentiometers at each colors as color would be changed with potentiometer too.
I put slide potentiometer as used another example code from the internet(address is at link).
At first, I found to add ControlP5 for put the potentiometer.
Then I added library at first,
import controlP5.*;
import controlP5.*;
ControlP5 cp5;
float sliderValue = 100;
void setup() {
size(600, 400);
cp5 = new ControlP5(this);
cp5.addSlider("sliderValue")
.setPosition(100, 100)
.setSize(300, 20)
.setRange(0, 255)
.setValue(sliderValue);
}
void draw() {
background(sliderValue); // スライダー値で背景の明るさを変える
fill(0);
text("Slider Value: " + sliderValue, 100, 150);
}
Then I asked chatGPT to
“How can I reflect the slider values in the background?”
Then chatGPT answered the code.
void draw() {
currentColor = color(sliderR, sliderG, sliderB); // スライダー値で背景色を作る
background(currentColor);
// Drawing by button
fill(baseColor);
ellipse(BaseX, BaseY, circleSize, circleSize);
fill(RedOff);
ellipse(RedX, RedY, circleSize, circleSize);
fill(GreenOff);
ellipse(GreenX, GreenY, circleSize, circleSize);
fill(BlueOff);
ellipse(BlueX, BlueY, circleSize, circleSize);
// スライダーの値を表示(デバッグ用)
fill(0);
textSize(16);
text("R: " + sliderR, 50, height - 60);
text("G: " + sliderG, 50, height - 40);
text("B: " + sliderB, 50, height - 20);
}
Serial Connect with Xiao C3¶
Next, I tried to put the neo pixel light which was changed to the selected color at processing.
For communicating Processing and Arduino, I asked to GPT as follows;
I want this code to reflect the colour of the led using serial communication,
can you tell me the code for SERIAL?
To send LED colours via serial communication from Processing, simply combine
the slider values (R, G, B) into a string and send it to the serial port.
For example, if you want to control LEDs by receiving values in the form R, G, B on the Arduino side,
you can write the following serial transmission code on the Processing side.
Processing Side
At setup():
String portName = "COM7"; // ←あなたの環境に合わせて
myPort = new Serial(this, portName, 9600);
At draw():
if (myPort != null) {
String sendString = int(sliderR) + "," + int(sliderG) + "," + int(sliderB) + "\n";
myPort.write(sendString);
}
void loop() {
if (Serial.available()) {
String input = Serial.readStringUntil('\n');
int comma1 = input.indexOf(',');
int comma2 = input.lastIndexOf(',');
if (comma1 > 0 && comma2 > comma1) {
int r = input.substring(0, comma1).toInt();
int g = input.substring(comma1 + 1, comma2).toInt();
int b = input.substring(comma2 + 1).toInt();
// ここで r, g, b をLEDに反映
}
}
}
Connect with Neo Pixel¶
It was first time to light the neo pixel, I checked the internet about it.
Adafruit_NeoPixel.h was needed for lighten the neo pixel.
So I added this library and made a code by the help of internet and chatGPT.
Code is below.(Neo Pixel)
Connect with RGB LED¶
After I could light on the Neopixel, I’d like to light with RGB LED too. I learnt using ledcAttach() for changing the LED color more smoothly.
Note
PWM (Pulse Width Modulation) (from chatGPT)
it’s a way to control the average power delivered to a device (like an LED or motor) by rapidly turning a signal ON and OFF.
Key concepts
Duty cycle → How much of the time the signal is ON.
0% → always off
50% → on half the time
100% → always on
Frequency → How fast you switch between ON and OFF.
Even at high frequencies, devices like LEDs or motors will smooth out the flicker, so you see it as dimmer or slower, not as fast blinking.
I wrote the neo pixel code using internet page as a reference.
Code is below(RGB LED)
Research¶
I’ve searched a lot about “Processing” this week. It was totally new language for me, but it seemed similar with arduino. I listed several links that I searched. I also check and learnt about neo pixel. I learnt Neo pixel has a library from my classmate and checked it.
What I’ve learnt this week¶
I’ve learnt several new languages, Processing, P5.js and Three.js. I tried to make a code with Processing. The codes in Arduino seem possible to create something that could be used as a reference.
Useful links¶
Code Example¶
Processing Side
/**
* Button.
*
* Click on one of the colored shapes in the
* center of the image to change the color of
* the background.
*/
import processing.serial.*;
import controlP5.*;
Serial myPort;
ControlP5 cp5;
//From instructor
String myString = null; //3. create a variable to receive the string from MCU
int nl = 10; //4. create a variable to represent the carriage return (end of message)
float myVal; //5. create a variable to hold a float number
int RedX, RedY; //Position of circle red button
int GreenX, GreenY; // Position of circle Green button
int BlueX, BlueY; // Position of circle blue button
int BaseX, BaseY; // Position of circle blue button
color baseColor, currentColor,Blackout;
color RedOff, RedOn;
color GreenOff, GreenOn;
color BlueOff, BlueOn;
int currentButton = 0;
int circleSize = 85; // Diameter of circle
int currentX = 0;
int currentY = 0;
int sliderR;
int sliderG;
int sliderB;
//from chatGPT
int lastR = -1;
int lastG = -1;
int lastB = -1;
//from chatGPT
boolean RedOver = false;
boolean GreenOver = false;
boolean BlueOver = false;
boolean BaseOver = true;
void setup() {
size(640, 360); // Board size
RedOff = color(150,0,0);
RedOn = color(255,0,0);
GreenOff = color(0, 150, 0);
GreenOn = color(0,255,0);
BlueOff = color(0, 0, 150);
BlueOn = color(0,0,255);
RedX = width/4;
RedY = height/4+circleSize/4;
GreenX = width/4*2;
GreenY = height/4+circleSize/4;
BlueX = (width/4)*3;
BlueY = height/4+circleSize/4;
BaseX = width-circleSize;
BaseY = height-circleSize;
baseColor = color(102);
currentColor = baseColor;
currentButton = -1;
Blackout = color(0);
ellipseMode(CENTER);
cp5 = new ControlP5(this);
cp5.addSlider("sliderR")
.setPosition(width/4-circleSize,height/2)
.setSize(150,20)
.setRange(0,255)
.setValue(127)
;
cp5.addSlider("sliderG")
.setPosition(width/4*2-circleSize,height/2)
.setSize(150,20)
.setRange(0,255)
.setValue(127)
;
cp5.addSlider("sliderB")
.setPosition((width/4)*3-circleSize,height/2)
.setSize(150,20)
.setRange(0,255)
.setValue(127)
;
// String portName = "/dev/cu.usbmodem2101"; //6. specify the COM port number where the MCU is connected
String portName = "/dev/cu.usbmodem101"; //6. specify the COM port number where the MCU is connected
myPort = new Serial(this,portName,9600); //7. initialize the Serial object
}
void draw(){
// update(mouseX, mouseY);
// select color
// Advised from chatGPT
currentColor = color(sliderR, sliderG, sliderB);
background(currentColor);
fill(Blackout);
ellipse(BaseX, BaseY, circleSize, circleSize);
fill(RedOff);
ellipse(RedX, RedY, circleSize, circleSize);
fill(GreenOff);
ellipse(GreenX, GreenY, circleSize, circleSize);
fill(BlueOff);
ellipse(BlueX, BlueY, circleSize, circleSize);
// Advised from chatgpt -slider
fill(0);
textSize(16);
text("R: " + sliderR, 50, height - 60);
text("G: " + sliderG, 50, height - 40);
text("B: " + sliderB, 50, height - 20);
/*
if (myPort != null) {
String sendString = int(sliderR) + "," + int(sliderG) + "," + int(sliderB) + "\n";
myPort.write(sendString);
println(sendString);
}
*/
// chatGPT
if (myPort != null) {
int r = int(sliderR);
int g = int(sliderG);
int b = int(sliderB);
if (r != lastR || g != lastG || b != lastB) {
String sendString = r + "," + g + "," + b + "\n";
myPort.write(sendString);
println(sendString);
lastR = r;
lastG = g;
lastB = b;
}
}
}
//void update(int x, int y) {
void update(){
if ( overCircle(BaseX, BaseY, circleSize)){ //Base
currentButton = 0;
}else if ( overCircle(RedX, RedY, circleSize) ) { //Red
currentButton = 1;
} else if ( overCircle(GreenX, GreenY, circleSize) ) { //Green
currentButton = 2;
} else if ( overCircle(BlueX, BlueY, circleSize) ) { //Blue
currentButton = 3;
} else {
currentButton = -1;
}
}
boolean overCircle(int x, int y, int diameter) {
float disX = x - mouseX;
float disY = y - mouseY;
if (sqrt(sq(disX) + sq(disY)) < diameter/2 ) {
return true;
} else {
return false;
}
}
void mousePressed() {
if (overCircle(BaseX, BaseY, circleSize)) {
currentButton = 0;
// Advised from chatGPT
cp5.getController("sliderR").setValue(0);
cp5.getController("sliderG").setValue(0);
cp5.getController("sliderB").setValue(0);
} else if (overCircle(RedX, RedY, circleSize)) {
currentButton = 1;
// Advised from chatGPT
cp5.getController("sliderR").setValue(255);
cp5.getController("sliderG").setValue(0);
cp5.getController("sliderB").setValue(0);
} else if (overCircle(GreenX, GreenY, circleSize)) {
currentButton = 2;
// Advised from chatGPT
cp5.getController("sliderR").setValue(0);
cp5.getController("sliderG").setValue(255);
cp5.getController("sliderB").setValue(0);
} else if (overCircle(BlueX, BlueY, circleSize)) {
currentButton = 3;
// Advised from chatGPT
cp5.getController("sliderR").setValue(0);
cp5.getController("sliderG").setValue(0);
cp5.getController("sliderB").setValue(255);
}
}
Arduino Side
(1) Neo Pixel
#include <Adafruit_NeoPixel.h>
#define Neopin D0
#define NUMPIXELS 8 // ネオピクセルの数(必要に応じて変更)
int r = 0;
int g = 0;
int b = 0;
Adafruit_NeoPixel pixels(NUMPIXELS, Neopin, NEO_GRB + NEO_KHZ800);
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
pixels.begin(); // 初期化
pixels.show(); // すべてのLEDをオフに
}
void loop() {
// from chatGPT
if (Serial.available()) {
String input = Serial.readStringUntil('\n');
int comma1 = input.indexOf(',');
int comma2 = input.lastIndexOf(',');
if (comma1 > 0 && comma2 > comma1) {
r = input.substring(0, comma1).toInt();
g = input.substring(comma1 + 1, comma2).toInt();
b = input.substring(comma2 + 1).toInt();
// ここで r, g, b をLEDに反映
for (int i = 0; i < NUMPIXELS; i++) {
pixels.setPixelColor(i, pixels.Color(r, g, b)); // R, G, B
}
pixels.show();
// delay(500);
}
}
// from chatGPT
}
(2) RGB LED
#define RED_PIN D0 // GPIOピン番号に合わせて変更
#define GREEN_PIN D1
#define BLUE_PIN D2
// Brightness correction (chatGPT)
// float redFactor = 0.45;
float redFactor = 1.0;
float greenFactor = 1.0 ;
float blueFactor = 1.0;
int r = 0, g = 0, b = 0;
void setup() {
Serial.begin(9600);
ledcAttach(RED_PIN, 5000, 8);
ledcAttach(GREEN_PIN, 5000, 8);
ledcAttach(BLUE_PIN, 5000, 8);
// ledcSetup(0, 5000, 8); // channel 0, freq 5kHz, resolution 8bit
// ledcAttachPin(RED_PIN, 0);
// ledcSetup(1, 5000, 8);
// ledcAttachPin(GREEN_PIN, 1);
// ledcSetup(2, 5000, 8);
// ledcAttachPin(BLUE_PIN, 2);
}
void loop() {
if (Serial.available()) {
String input = Serial.readStringUntil('\n');
int comma1 = input.indexOf(',');
int comma2 = input.lastIndexOf(',');
if (comma1 > 0 && comma2 > comma1) {
r = input.substring(0, comma1).toInt();
g = input.substring(comma1 + 1, comma2).toInt();
b = input.substring(comma2 + 1).toInt();
// Correction to 0~255
int correctedR = constrain(r * redFactor, 0, 255);
int correctedG = constrain(g * greenFactor, 0, 255);
int correctedB = constrain(b * blueFactor, 0, 255);
// 共通カソード用(値そのまま)
// analogWrite(RED_PIN, r);
// analogWrite(GREEN_PIN, g);
// analogWrite(BLUE_PIN, b);
//Write PWM values using ledcWrite (from chatGPT)
ledcWrite(RED_PIN, correctedR); // channel 0 → RED
ledcWrite(GREEN_PIN, correctedG); // channel 1 → GREEN
ledcWrite(BLUE_PIN, correctedB); // channel 2 → BLUE
// 共通アノード用(反転値)
// analogWrite(RED_PIN, 255 - r);
// analogWrite(GREEN_PIN, 255 - g);
// analogWrite(BLUE_PIN, 255 - b);
}
}
}