I tried making a pokeball image with my oled and it worked the first time with my code however when I answered correctly first of all it didnt pop up on lcd, at the same time oled didnt show anything either, however the wiring is fine and other image examples such as heart worked fine to be used multiple times. I tried asking chat gpt for help but it destroyed my image. Can I have some help please?
This code is supposed to be a spell checking device for kids to type letters on a keypad and check for spelling thus learn. The way it should work is you type your word with letters , it spell checks the word and you get a "incorrect!" or a "correct!" then you try again. there are a few parts which are plans for newer features i will soon add. It also displays the image of the word on the OLED and you type words that appear in the LCD screen.
here is the code:
#include <Wire.h>
#include <SparkFun_Qwiic_Keypad_Arduino_Library.h>
#include <SparkFun_Qwiic_OLED.h> // Include the SparkFun Qwiic OLED library
const int mercurySwitchPin = 2; // Replace with the actual pin number where the switch is connected
int Mercury = 0;
#include <SerLCD.h>
SerLCD lcd;
// Initialize TwoWire objects for two keypads
TwoWire Wire1;
TwoWire Wire2;
// Initialize keypad objects
KEYPAD keypad1;
KEYPAD keypad2;
// Variables to hold the current state
String finalString = "";
boolean startMessageShown = false;
// List of words for the game
String words[] = {/*"smile","circle","triangle","rectangle","diamond","square","heart",*/"heart"}; //smile","circle","triangle","rectangle","diamond", //{"smile","circle","triangle","rectangle","diamond","square","heart"};
int arraySize = sizeof(words) / sizeof(words[0]);
String currentWord;
// Declare width and height as global variables
int width;
int height;
int index;
// Mapping for keypad 1
char keypad1Mapping[4][3] = {
{'a', 'b', 'c'},
{'d', 'e', 'f'},
{'g', 'h', 'i'},
{'*', 'j', 'k'}
};
// Mapping for keypad 2
char keypad2Mapping[4][3] = {
{'l', 'm', 'n'},
{'o', 'p', 'q'},
{'r', 's', 't'},
{'u', 'v', '#'}
};
// Enum to represent the game state
enum GameState {
WAIT_FOR_START,
IN_GAME,
WAIT_FOR_RESTART
};
// Initialize game state
GameState currentState = WAIT_FOR_START;
QwiicMicroOLED myOLED; // Create an instance of the Qwiic Micro OLED object
void setup(void) {
pinMode(mercurySwitchPin, INPUT); // Set the pin as an input
Serial.begin(9600); // Initialize serial communication
lcd.begin(Wire);
lcd.clear();
Wire1.begin();
Wire2.begin();
// Check if keypads are connected
if (keypad1.begin(Wire1, 0x4B) == false || keypad2.begin(Wire2, 0x2A) == false) {
Serial.println("One or both keypads do not appear to be connected. Please check wiring. Freezing...");
while (1);
}
// Initialize the OLED device and related graphics system
if (myOLED.begin() == false) {
Serial.println("Device begin failed. Freezing...");
while (1);
}
// Save device dims for the test routines
width = myOLED.getWidth();
height = myOLED.getHeight();
// Seed the random number generator
randomSeed(analogRead(0));
Serial.println("Initial analogRead(0): " + String(analogRead(0)));
Serial.println("Array Size: " + String(arraySize));
int randomIndex = random(arraySize);
Serial.println("Random Index: " + String(randomIndex));
}
int generateRandomIndex(int arraySize) {
long seed = 0;
for (int i = 0; i < 32; i++) {
seed ^= long(analogRead(0)) << i;
delay(1);
}
randomSeed(seed);
int randomIndex = random(arraySize);
return randomIndex;
}
// Function to draw a circle
void drawCircle(int width, int height) {
myOLED.circle(width / 2, height / 2, height / 4); // Center at (width/2, height/2) with radius height/4
}
void drawPokeBall(int width, int height) {
int circleCenterX = width / 2;
int circleCenterY = height / 2;
int circleRadius = height / 4;
int pixelOffRadius = width / 15;
int offsetY = 1;
myOLED.circle(circleCenterX, circleCenterY, circleRadius);
int x1 = circleCenterX - circleRadius;
int x2 = circleCenterX + circleRadius;
int y = circleCenterY + offsetY;
int y2 = circleCenterY - offsetY;
myOLED.line(x1, y, x2, y);
myOLED.line(x1, y2, x2, y2);
int radius = width / 12;
for (int y3 = -radius; y3 <= radius; y3++) {
for (int x3 = -radius; x3 <= radius; x3++) {
if (x3 * x3 + y3 * y3 <= radius * radius) {
myOLED.pixel(circleCenterX + x3, circleCenterY + y3);
}
}
}
int radius3 = width / 14;
for (int y5 = -radius3; y5 <= radius3; y5++) {
for (int x5 = -radius3; x5 <= radius3; x5++) {
if (x5 * x5 + y5 * y5 <= radius3 * radius3) {
myOLED.pixel(circleCenterX + x5, circleCenterY + y5);
}
}
}
for (int y6 = -pixelOffRadius; y6 <= pixelOffRadius; y6++) {
for (int x6 = -pixelOffRadius; x6 <= pixelOffRadius; x6++) {
if (x6 * x6 + y6 * y6 <= pixelOffRadius * pixelOffRadius) {
myOLED.pixel(circleCenterX + x6, circleCenterY + y6, false);
}
}
}
int radius4 = width / 19;
for (int y6 = -radius4; y6 <= radius4; y6++) {
for (int x6 = -radius4; x6 <= radius4; x6++) {
if (x6 * x6 + y6 * y6 <= radius4 * radius4) {
myOLED.pixel(circleCenterX + x6, circleCenterY + y6);
}
}
}
}
// Function to draw a square
void drawSquare(int width, int height) {
int sideLength = min(width, height) / 2; // Ensure the square fits within the screen
int x = width / 2 - sideLength / 2;
int y = height / 2 - sideLength / 2;
myOLED.rectangle(x, y, sideLength, sideLength); // Top-left corner at (x, y) with side length 'sideLength'
}
// Function to draw a rectangle
void drawRectangle(int width, int height) {
myOLED.rectangle(width / 4, height / 4, width / 2, height / 4); // Top-left corner at (width/4, height/4), width width/2, height height/4
}
// Function to draw a Pokeball
/* void drawPokeBall(int width, int height){
int circleCenterX = width / 2;
int circleCenterY = height / 2;
int circleRadius = height / 4;
int radius = width / 12;
int radius2 = width / 13;
int offsetY = 1; // Offset from the middle in the y direction
int pixelOffRadius = width / 15;
int radius3 = width / 14;
int radius4 = width / 19;
int x1 = circleCenterX - circleRadius;
int x2 = circleCenterX + circleRadius;
int y = circleCenterY + offsetY;
int y2 = circleCenterY - offsetY;
myOLED.circle(width / 2, height / 2, height / 4); // Center at (width/2, height/2) with radius height/4
myOLED.line(x1, y, x2, y);
myOLED.line(x1, y2, x2, y2);
for (int y3 = -radius; y3 <= radius; y3++) {
for (int x3 = -radius; x3 <= radius; x3++) {
if (x3 * x3 + y3 * y3 <= radius * radius) {
myOLED.pixel(circleCenterX + x3, circleCenterY + y3);
}
}
}
// Draw the black circle
for (int y5 = -radius3; y5 <= radius3; y5++) {
for (int x5 = -radius3; x5 <= radius3; x5++) {
if (x5 * x5 + y5 * y5 <= radius3 * radius3) {
myOLED.pixel(circleCenterX + x5, circleCenterY + y5);
}
}
}
// Turn off pixels coincident with the pixelOffRadius
for (int y6 = -pixelOffRadius; y6 <= pixelOffRadius; y6++) {
for (int x6 = -pixelOffRadius; x6 <= pixelOffRadius; x6++) {
if (x6 * x6 + y6 * y6 <= pixelOffRadius * pixelOffRadius) {
myOLED.pixel(circleCenterX + x6, circleCenterY + y6, false); // Turn off the pixel
}
}
}
// Draw the filled circle at the center
for (int y6 = -radius4; y6 <= radius4; y6++) {
for (int x6 = -radius4; x6 <= radius4; x6++) {
if (x6 * x6 + y6 * y6 <= radius4 * radius4) {
myOLED.pixel(circleCenterX + x6, circleCenterY + y6);
}
}
}
}
*/
// Function to draw a triangle
void drawTriangle(int width, int height) {
myOLED.line(width / 4, 3 * height / 4, width / 2, height / 4); // First line
myOLED.line(width / 2, height / 4, 3 * width / 4, 3 * height / 4); // Second line
myOLED.line(3 * width / 4, 3 * height / 4, width / 4, 3 * height / 4); // Third line
}
// Function to draw a diamond shape
void drawDiamond(int width, int height) {
int centerX = width / 2;
int centerY = height / 2;
int halfDiag = 10; // Half of the diagonal length
// Calculate corner points
int topX = centerX;
int topY = centerY - halfDiag;
int bottomX = centerX;
int bottomY = centerY + halfDiag;
int leftX = centerX - halfDiag;
int leftY = centerY;
int rightX = centerX + halfDiag;
int rightY = centerY;
// Draw lines to form the diamond
myOLED.line(topX, topY, leftX, leftY); // Top to left
myOLED.line(topX, topY, rightX, rightY); // Top to right
myOLED.line(bottomX, bottomY, leftX, leftY); // Bottom to left
myOLED.line(bottomX, bottomY, rightX, rightY); // Bottom to right
}
// Function to draw a completely filled heart shape
void drawFilledHeart(int width, int height) {
int centerX = width / 2;
int centerY = height / 2;
// Fill the two circles for the lobes of the heart
for (int y = -10; y <= 10; y++) {
for (int x = -10; x <= 10; x++) {
if (x*x + y*y <= 100) {
myOLED.pixel(centerX - 10 + x, centerY - 10 + y);
myOLED.pixel(centerX + 10 + x, centerY - 10 + y);
}
}
}
// Fill the inverted V shape for the bottom part of the heart
for (int y = 0; y <= 25; y++) {
for (int x = -15 + y; x <= 15 - y; x++) {
myOLED.pixel(centerX + x, centerY + y);
}
}
// Fill the small gap between the circles and the triangle
for (int y = -10; y <= 0; y++) {
for (int x = -10; x <= 10; x++) {
myOLED.pixel(centerX + x, centerY + y);
}
}
// Update the display
myOLED.display();
}
// Function to draw a smile
void drawSmile(int width, int height) {
// Draw eyes
int eyeRadius = 4;
int leftEyeX = width / 2 - 5;
int rightEyeX = width / 2 + 5;
int eyeY = height / 2 - 5;
myOLED.circle(leftEyeX, eyeY, eyeRadius);
myOLED.circle(rightEyeX, eyeY, eyeRadius);
// Draw mouth
int mouthRadius = 8;
int mouthX = width / 2;
int mouthY = height / 2 + 2;
for (int i = 0; i <= 180; i++) {
int x = mouthX + mouthRadius * cos(i * PI / 180.0);
int y = mouthY + mouthRadius * sin(i * PI / 180.0);
myOLED.pixel(x, y);
}
}
//Loop contains actions for the game
void loop() {
// Read the state of the mercury switch
int switchState = digitalRead(mercurySwitchPin);
// Check if the switch is on (HIGH)
if (switchState == HIGH) {
Mercury = 1;
} else {
Mercury = 0;
}
// Print the state to the serial monitor (optional)
//Serial.println(Mercury);
// Update keypad states
keypad1.updateFIFO();
keypad2.updateFIFO();
// Read button presses
char button1 = keypad1.getButton();
char button2 = keypad2.getButton();
// Game state logic
switch (currentState) {
case WAIT_FOR_START:
// Show start message once
if (!startMessageShown) {
lcd.println("Press # to start.");
Serial.println("Press # to start the game.");
startMessageShown = true;
}
// Start the game when # is pressed
if (button2 == '#') {
currentState = IN_GAME;
finalString = "";
index = generateRandomIndex(arraySize);
currentWord = words[index];
Serial.println("Game started, you must match with the word " + currentWord + ". Begin typing.");
lcd.clear();
lcd.println("Spell The Image!");
myOLED.display();
// Word to OLED picture
if (currentWord == "rectangle") {
drawRectangle(width, height);
} else if (currentWord == "circle") {
drawCircle(width, height);
} else if (currentWord == "square") {
drawSquare(width, height);
} else if (currentWord == "triangle") {
drawTriangle(width, height);
} else if (currentWord == "smile") {
drawSmile(width, height);
} else if (currentWord == "diamond") {
drawDiamond(width, height);
}else if (currentWord == "heart") {
drawFilledHeart(width, height);
} else if (currentWord == "pokeball") {
drawPokeBall(width, height);
}
//myOLED.erase(); // Clear the display
myOLED.display();
}
break;
// Handle keypad 1 input
case IN_GAME:
if (button1 != 0) {
int row = (button1 - '1') / 3;
int col = (button1 - '1') % 3;
if (button1 >= '1' && button1 <= '9') {
finalString += keypad1Mapping[row][col];
} else if (button1 == '0') {
finalString += keypad1Mapping[3][1]; // 'j'
} else if (button1 == '*') {
if (finalString.length() > 0) {
finalString.remove(finalString.length() - 1);
}
} else if (button1 == '#') {
finalString += keypad1Mapping[3][2]; // 'k'
}
Serial.println(finalString);
lcd.clear();
lcd.println(finalString);
}
// Handle keypad 2 input
if (button2 != 0) {
if (button2 >= '1' and button2 <= '9') {
finalString += char('l' + (button2 - '1'));
} else if (button2 == '0') {
finalString += 'v';
} else if (button2 == '*') {
finalString += 'u';
} else if (button2 == '#') {
Serial.println("Submitted: " + finalString);
if (finalString == currentWord) {
Serial.println("Correct! Press # to play again.");
lcd.clear();
lcd.println("Correct, (#)");
currentState = WAIT_FOR_RESTART;
} else {
Serial.println("Incorrect word. Try again.");
lcd.clear();
lcd.println("Incorrect. Try again!");
}
finalString = "";
}
Serial.println(finalString);
lcd.clear();
lcd.println(finalString);
myOLED.erase();
}
break;
// Restart the game when # is pressed
case WAIT_FOR_RESTART:
if (button2 == '#'); // if (Mercury = 1)
{
currentState = IN_GAME;
finalString = "";
index = generateRandomIndex(arraySize);
currentWord = words[index];
Serial.println("Game started, you must match with the word " + currentWord + ". Begin typing.");
myOLED.erase(); // Clear the display
myOLED.display();
//The if statements below link the 'random work' to a image displayed on the OLED
if (currentWord == "rectangle") {
drawRectangle(width, height);
} else if (currentWord == "circle") {
drawCircle(width, height);
} else if (currentWord == "square") {
drawSquare(width, height);
} else if (currentWord == "triangle") {
drawTriangle(width, height);
} else if (currentWord == "smile") {
drawSmile(width, height);
}else if (currentWord == "diamond") {
drawDiamond(width, height);
}else if (currentWord == "heart") {
drawFilledHeart(width, height);
}
myOLED.display();
}
break;
}
delay(100);
}