Snake Game
Snake Game
Snake Game
import serial
import time
import keyboard # pip install keyboard for monitoring key presses
# Setup the serial connection to the Arduino (adjust 'COM3' and baudrate as
necessary)
ser = serial.Serial('COM3', 9600)
time.sleep(2) # Give time to establish connection
def send_command(command):
ser.write(command.encode()) # Send the keypress to Arduino
try:
while True:
if keyboard.is_pressed('up'):
send_command('U') # 'U' for Up
print("Up Arrow Pressed")
time.sleep(0.1) # Small delay to avoid multiple sends
elif keyboard.is_pressed('down'):
send_command('D') # 'D' for Down
print("Down Arrow Pressed")
time.sleep(0.1)
elif keyboard.is_pressed('left'):
send_command('L') # 'L' for Left
print("Left Arrow Pressed")
time.sleep(0.1)
elif keyboard.is_pressed('right'):
send_command('R') # 'R' for Right
print("Right Arrow Pressed")
time.sleep(0.1)
finally:
ser.close() # Ensure the serial port is closed on exit
#include <DMD.h>
#include <TimerOne.h>
#define WIDTH 32
#define HEIGHT 16
// Snake variables
struct Point {
int x, y;
};
void scanDMD() {
dmd.scanDisplayBySPI();
}
void setup() {
Timer1.initialize(5000);
Timer1.attachInterrupt(scanDMD);
dmd.clearScreen(true);
void loop() {
// Check for serial input from the computer
if (Serial.available() > 0) {
char input = Serial.read();
if (input == 'U' && direction != 2) direction = 0; // Up
else if (input == 'D' && direction != 0) direction = 2; // Down
else if (input == 'L' && direction != 1) direction = 3; // Left
else if (input == 'R' && direction != 3) direction = 1; // Right
}
moveSnake();
checkFood();
drawSnake();
delay(200); // Controls snake speed
}
void moveSnake() {
// Move the snake's body
for (int i = snakeLength - 1; i > 0; i--) {
snake[i] = snake[i - 1];
}
void generateFood() {
food.x = random(WIDTH);
food.y = random(HEIGHT);
}
void checkFood() {
// If the snake eats the food
if (snake[0].x == food.x && snake[0].y == food.y) {
snakeLength++; // Increase the snake length
generateFood(); // Generate a new piece of food
}
}
void drawSnake() {
dmd.clearScreen(true); // Clear the screen
import pygame
import time
import random
pygame.init()
# Define colors
black = (0, 0, 0)
red = (213, 50, 80)
green = (0, 255, 0)
blue = (50, 153, 213)
# Screen size
screen_width = 600
screen_height = 400
screen = pygame.display.set_mode((screen_width, screen_height))
# Game clock
clock = pygame.time.Clock()
# Snake settings
snake_block = 10
snake_speed = 15
# Fonts
font_style = pygame.font.SysFont("bahnschrift", 25)
def game_loop():
game_over = False
game_close = False
# Movement variables
x_change = 0
y_change = 0
while game_close:
screen.fill(blue)
message("You Lost! Press Q-Quit or C-Play Again", red)
pygame.display.update()
# Boundary conditions
if x >= screen_width or x < 0 or y >= screen_height or y < 0:
game_close = True
x += x_change
y += y_change
screen.fill(black)
# Draw food
pygame.draw.rect(screen, red, [food_x, food_y, snake_block, snake_block])
draw_snake(snake_block, snake_list)
pygame.display.update()
clock.tick(snake_speed)
pygame.quit()
quit()
game_loop()
from ursina import *
from random import randint
app = Ursina()
def update():
global direction, timer
# Movement control
if held_keys['w']:
direction = Vec3(0, 1, 0) # Move up
elif held_keys['s']:
direction = Vec3(0, -1, 0) # Move down
elif held_keys['a']:
direction = Vec3(-1, 0, 0) # Move left
elif held_keys['d']:
direction = Vec3(1, 0, 0) # Move right
# Timer-based movement
timer += time.dt
if timer >= time_step:
timer = 0
move_snake()
def move_snake():
# Move the snake's body
for i in range(len(snake) - 1, 0, -1):
snake[i].position = snake[i - 1].position
def grow_snake():
# Add a new segment to the snake's body
new_segment = Entity(model='cube', color=color.green, position=snake[-
1].position)
snake.append(new_segment)
app.run()
in a vfD the frequency and voltage are both altered write code for atmega328 in
arduino to control an h bridge using two pins so that using pwm we can vary the
above parameters also comment the each line of code
ChatGPT said:
ChatGPT
Memory updated
Here’s an example Arduino code to control an H-bridge using two pins (e.g., PIN1
and PIN2) to vary both frequency and voltage using PWM on an ATmega328 (e.g.,
Arduino Uno). In a Variable Frequency Drive (VFD), both the PWM frequency and
voltage (i.e., duty cycle) are modulated to control the motor speed.
void setup() {
// Set the H-bridge control pins as outputs
pinMode(PIN1, OUTPUT);
pinMode(PIN2, OUTPUT);
void loop() {
// Vary the frequency by adjusting the delay between switching directions
unsigned long delayTime = 1000 / (2 * pwmFrequency); // Calculate half-period in
milliseconds
// The frequency of PWM is controlled by the Timer 1 prescaler and the value in
OCR1A/B registers.
// Frequency of PWM = (16 MHz / (prescaler * 256)) = 16 MHz / (8 * 256) = ~7.8
kHz
}
// You can add more functions or logic to dynamically adjust the frequency or duty
cycle
Explanation of Code:
PIN Definitions:
cpp
Copy code
const int PIN1 = 9;
const int PIN2 = 10;
Pins 9 and 10 are defined as the control pins for the H-bridge. These are PWM-
capable pins on the ATmega328 (Arduino Uno).
PWM Variables:
cpp
Copy code
int pwmFrequency = 100;
int pwmDutyCycle = 128;
pwmFrequency: Initial frequency set to 100 Hz.
pwmDutyCycle: Initial duty cycle set to 50% (128 out of 255).
Setup Function:
cpp
Copy code
pinMode(PIN1, OUTPUT);
pinMode(PIN2, OUTPUT);
setupPWM();
The pinMode function sets the control pins as outputs.
The setupPWM() function configures Timer 1 for fast PWM mode.
Loop Function:
cpp
Copy code
analogWrite(PIN1, pwmDutyCycle);
analogWrite(PIN2, 0);
delay(delayTime);
The loop alternates between turning PIN1 and PIN2 on/off to switch the direction of
the H-bridge, effectively creating an alternating signal (for AC motor control).
The duty cycle is applied to control the average voltage, while the frequency is
controlled by the delay between switches.
Adjust Frequency and Duty Cycle:
cpp
Copy code
pwmDutyCycle = (pwmDutyCycle + 1) % 256;
pwmFrequency = (pwmFrequency + 1) % 100;
This section is for simulating changes in voltage and frequency. In a real-world
application, you'd modify this logic based on user input or sensor feedback.
setupPWM Function:
cpp
Copy code
TCCR1A = (1 << WGM10) | (1 << WGM12) | (1 << COM1A1) | (1 << COM1B1);
TCCR1B = (1 << WGM12) | (1 << CS11);
This configures Timer 1 in Fast PWM mode to generate the PWM signals on pins 9 and
10.
The prescaler is set to 8, giving you a PWM frequency of ~7.8 kHz (adjustable with
the Timer settings).
What You Can Adjust:
Duty Cycle (Voltage): Adjust the pwmDutyCycle to control the effective voltage
across the load.
Switching Frequency: Change pwmFrequency to control how fast the H-bridge switches
direction, which impacts the output frequency of the AC waveform.
This code will give you control over both the frequency (switching speed) and
voltage (through the duty cycle) in a simple VFD-like application.
You said:
you didn't create the look up table but feel free to tell me if it was'nt necessary
for this
ChatGPT said:
ChatGPT
You're right to mention a lookup table, which is often used in applications like
Sinusoidal PWM (SPWM) to generate a smoothly modulated sinusoidal signal. In this
case, I did not include one because the example provided uses a more basic approach
that modulates frequency and duty cycle linearly, without attempting to create a
true sine wave.
You are trying to create a sinusoidal PWM (SPWM) signal to approximate a sine wave
in an inverter or VFD.
The duty cycle needs to follow a precise mathematical function (like a sine wave)
for each PWM cycle to control the output voltage in the form of an AC signal.
Why It Wasn’t Necessary Here
In the example code:
The duty cycle is varied linearly for demonstration purposes. It’s not trying to
generate a smooth sinusoidal wave.
The frequency is changed without specifically following the shape of a sine wave.
If you're aiming for AC output with smooth waveform control, a lookup table would
be crucial to adjust the PWM signal according to a sinusoidal waveform pattern. In
this case, for each point in the waveform (e.g., 0° to 360°), the lookup table
would hold precomputed values of the sine wave that are used to modulate the duty
cycle.
cpp
Copy code
// Define a lookup table for a sine wave with 16 steps (example)
const uint8_t sineTable[16] = {
128, 176, 218, 246, 255, 246, 218, 176,
128, 80, 38, 10, 0, 10, 38, 80
};
sineTable[] holds precomputed values of the sine wave, scaled to the range of 0–255
(for 8-bit PWM).
The PWM duty cycle is adjusted at each step based on the lookup table, which would
create a smoother approximation of a sine wave when controlling an H-bridge.
You said:
so could we use the look up table and still have control over both frequence and
voltage
ChatGPT said:
ChatGPT
Yes, you can definitely use a lookup table for Sinusoidal PWM (SPWM) and still have
control over both the frequency and voltage of the output. Here’s how:
For example:
A full sine wave lookup table (e.g., values ranging from 0 to 255) will output the
maximum voltage.
To reduce the voltage, you scale the values from the lookup table down by
multiplying each by a factor less than 1. This effectively reduces the amplitude of
the waveform without affecting its frequency.
2. Control of Frequency
The frequency is controlled by how quickly you move through the values in the sine
lookup table (i.e., the step size and time delay between steps). By increasing the
rate at which you move through the table, you effectively increase the output
frequency.
For example:
If you go through the lookup table values more quickly, the waveform will complete
more cycles per second, increasing the frequency.
If you move through the table values more slowly, the frequency decreases.
Code Example with Lookup Table for Both Voltage and Frequency Control
Here’s an updated version of the code that uses a lookup table for generating SPWM
and allows control over both the frequency and voltage:
cpp
Copy code
// Define a lookup table for a sine wave (16 steps for example)
const uint8_t sineTable[16] = {
128, 176, 218, 246, 255, 246, 218, 176,
128, 80, 38, 10, 0, 10, 38, 80
};
// Timing variables
unsigned long lastUpdateTime = 0;
unsigned long timePerStep; // Time between steps in microseconds
void setup() {
// Set pins as output
pinMode(9, OUTPUT); // PWM pin for H-bridge side 1
pinMode(10, OUTPUT); // PWM pin for H-bridge side 2
// Calculate the time delay between steps based on the desired frequency
timePerStep = (1000000 / (frequency * 16)); // 16 steps per waveform cycle
}
void loop() {
// Go through the lookup table to generate SPWM
for (int i = 0; i < 16; i++) {
// Check if it's time to update the PWM signal based on the frequency
if (micros() - lastUpdateTime >= timePerStep) {
// Apply scaled PWM from sine lookup table to control voltage (using
analogWrite)
analogWrite(9, sineTable[i] * voltageScale); // Side 1
analogWrite(10, 0); // Side 2 off
delayMicroseconds(timePerStep / 2); // Half-period delay
The sineTable holds precomputed values of the sine wave, scaled from 0 to 255.
These values are used to modulate the duty cycle of the PWM output.
Voltage Control:
The voltageScale variable controls the amplitude of the sine wave. By multiplying
each value in the lookup table by this factor, you can reduce the output voltage
(e.g., setting voltageScale = 0.5 will cut the voltage in half).
Frequency Control:
The frequency variable controls the time delay between steps through the lookup
table (timePerStep).
As the frequency increases, timePerStep becomes smaller, meaning the loop iterates
through the sine table faster, generating a higher output frequency.
H-Bridge Switching:
The H-bridge switches direction at each half-cycle (every 8 steps in the 16-step
lookup table) to create a full AC cycle.
Controlling Both Voltage and Frequency:
Voltage is controlled by adjusting the voltageScale factor, which affects how much
of the PWM duty cycle from the sine table is applied to the H-bridge. A smaller
scale reduces the output voltage.
Frequency is controlled by adjusting the frequency variable, which changes how fast
the code moves through the sine table. A higher frequency means shorter time steps,
leading to a higher output frequency.
Summary:
Using a lookup table to generate SPWM gives you precise control over both the
voltage (via duty cycle scaling) and frequency (via timing control). This approach
is ideal for applications like VFDs, where you need to vary both parameters to
control a motor or AC signal output.
Share
You said:
how can i make pwm using switching
ChatGPT said:
ChatGPT
To create Pulse Width Modulation (PWM) using switching, you control a switch
(usually a transistor or MOSFET) to toggle between on and off states at a fixed
frequency. By varying the time the switch stays "on" during each cycle (the duty
cycle), you can control the average voltage or power delivered to the load. Here’s
a general approach to generating PWM with switching:
Using Arduino:
Use the analogWrite() function to generate a PWM signal on certain pins (pins like
3, 5, 6, 9, 10, and 11 on most Arduino boards).
The analogWrite(pin, value) function allows you to set a duty cycle, where value is
between 0 (0% duty cycle) and 255 (100% duty cycle).
Example:
cpp
Copy code
int pwmPin = 9; // Define the pin for PWM
int dutyCycle = 127; // Set duty cycle to 50% (127 out of 255)
void setup() {
pinMode(pwmPin, OUTPUT);
}
void loop() {
analogWrite(pwmPin, dutyCycle); // Generate PWM
}
4. Vary the Duty Cycle
The duty cycle controls the ratio of "on" to "off" time. A higher duty cycle means
the switch stays on longer, providing more power to the load.
You can vary the duty cycle over time by changing the analogWrite() value in the
loop or using a sensor or input for control.
5. Filtering (Optional)
If you need to smooth the PWM output (for example, to create a variable DC
voltage), you can add a low-pass filter (a capacitor and resistor) to the output.
6. Driving Higher Power Loads
If the load requires more current than the microcontroller can provide, use the PWM
output to drive a transistor or MOSFET, which will switch a larger current for the
load.
Example with a MOSFET:
cpp
Copy code
int pwmPin = 9; // PWM output pin connected to the gate of a MOSFET
int dutyCycle = 127; // 50% duty cycle
void setup() {
pinMode(pwmPin, OUTPUT);
}
void loop() {
analogWrite(pwmPin, dutyCycle); // Control the MOSFET switching
}
With this method, the PWM signal controls the MOSFET, which in turn switches the
power to the load (e.g., a motor, light, or heater).
You can adjust the frequency and duty cycle to fit your needs, whether it’s
controlling a motor, dimming LEDs, or regulating power.
You said:
an spwm for 50 hz using switching
ChatGPT said:
ChatGPT
To generate a Sinusoidal Pulse Width Modulation (SPWM) signal for a 50 Hz output
using switching, you need to approximate a sinusoidal waveform by varying the duty
cycle of a high-frequency PWM signal. SPWM is commonly used in inverters, motor
drives, and other AC power applications.
Here’s a general approach:
Implementation on Arduino
Here’s an example of how to generate SPWM using an Arduino:
void setup() {
// Set up the PWM pin as output
pinMode(pwmPin, OUTPUT);
void loop() {
unsigned long startTime = micros(); // Record the start time
PWM Duty Cycle Variation: In each iteration of the loop, analogWrite() adjusts the
duty cycle of the PWM output according to the current value from the sine table.
This creates the SPWM pattern.
Timing Control: The loop runs at a fixed time interval to ensure that the sine wave
frequency stays at 50 Hz. The delayMicroseconds() ensures the timing for each step,
maintaining the proper waveform shape.
Additional Considerations:
Filtering: To smooth the SPWM output into a clean sine wave, use an LC low-pass
filter at the output. The filter removes the high-frequency PWM components, leaving
a sinusoidal waveform.
Switching Device: Use a MOSFET or IGBT to handle higher power loads when necessary.
The PWM output from the microcontroller controls the gate of the MOSFET.
This method gives you an approximation of a sine wave using switching, which is
commonly used in inverters and motor controllers to create AC waveforms from DC
power.
You said:
why do you use this 127.5 and how do you come with it
ChatGPT said:
ChatGPT
The value 127.5 is used to normalize the sine wave values to fit into the 8-bit PWM
range of 0 to 255. Here’s a detailed breakdown of how and why this value is used:
Scale the amplitude: Since the sine wave produces values between -1 and 1, you need
to scale this to fit within the 0-255 range. You do this by first converting the
sine wave to a positive-only range.
Add 1 to the sine value to shift it from the range [-1, 1] to [0, 2].
Rescale to PWM range: Now you need to map this new range [0, 2] to the 8-bit PWM
range [0, 255]. You can do this by multiplying by half the maximum PWM value:
PWM_value
=
(
sine_value
+
1
)
×
127.5
PWM_value=(sine_value+1)×127.5
127.5 is used because:
255
/
2
=
127.5
255/2=127.5
This effectively rescales the sine wave into a range from 0 to 255.
3. Resulting Formula
The formula used in the code:
cpp
Copy code
sineTable[i] = (uint8_t)((sin(2 * PI * i / resolution) + 1) * 127.5);
works as follows:
sin(2 * PI * i / resolution): Calculates the sine value for a given step i in the
cycle.
+ 1: Shifts the sine wave from [-1, 1] to [0, 2].
* 127.5: Scales the shifted sine wave from [0, 2] to [0, 255] so it fits the PWM
output range.
4. Example Calculations
For maximum sine value (sin(π/2) = 1):
PWM_value
=
(
1
+
1
)
×
127.5
=
2
×
127.5
=
255
PWM_value=(1+1)×127.5=2×127.5=255
So, the PWM signal will output its maximum duty cycle (fully on).
PWM_value
=
(
−
1
+
1
)
×
127.5
=
0
×
127.5
=
0
PWM_value=(−1+1)×127.5=0×127.5=0
The PWM signal will output its minimum duty cycle (fully off).
PWM_value
=
(
0
+
1
)
×
127.5
=
1
×
127.5
=
127.5
≈
128
PWM_value=(0+1)×127.5=1×127.5=127.5≈128
The PWM signal will output a 50% duty cycle (half on, half off).
Summary
The 127.5 comes from the need to:
Shift the sine wave from the range [-1, 1] to [0, 2].
Scale it to fit the 0-255 range of 8-bit PWM by multiplying by 127.5, which is half
of 255.
This scaling allows you to output the sinusoidal waveform using standard PWM
hardware with 8-bit resolution.