diff --git a/Processing.pdf b/Processing.pdf new file mode 100644 index 0000000..a24dcb4 Binary files /dev/null and b/Processing.pdf differ diff --git a/Processing/Apps/App_01_1_1_Oscilloscope/App_01_1_1_Oscilloscope.pde b/Processing/Apps/App_01_1_1_Oscilloscope/App_01_1_1_Oscilloscope.pde new file mode 100644 index 0000000..1103e40 --- /dev/null +++ b/Processing/Apps/App_01_1_1_Oscilloscope/App_01_1_1_Oscilloscope.pde @@ -0,0 +1,136 @@ +/******************************************************************************* //<>// + * Sketch App_01_1_1_Oscilloscope + * Author Freenove (http://www.freenove.com) + * Date 2016/08/26 + ****************************************************************************** + * Brief + * This sketch is used to make an oscilloscope + *************************************p***************************************** + * Copyright + * Copyright © Freenove (http://www.freenove.com) + * License + * Creative Commons Attribution ShareAlike 3.0 + * (http://creativecommons.org/licenses/by-sa/3.0/legalcode) + ****************************************************************************** + */ +import processing.io.*; + +PCF8591 pcf = new PCF8591(0x48); +int[] analogs; // Analog data send from serial device +int analogsCount; // Length of analogs[] array +int voltage = 0; // Voltage +int hMult = 1; // Horizontal zoom ratio, relative to 1 second +boolean pause = false; // Storage is suspended display + +void setup() +{ + size(530, 290); + background(102); + textAlign(CENTER, CENTER); + textSize(64); + text("Starting...", width / 2, (height - 40) / 2); + textSize(16); + text("www.freenove.com", width / 2, height - 20); + textAlign(LEFT, CENTER); + + analogsCount = width / 2; + analogs = new int[analogsCount]; + for (int i = 0; i < analogsCount; i++) + analogs[i] = -1; +} + +void draw() +{ + + int analog = pcf.analogRead(0); //serialDevice.requestAnalog(); + if (analog != -1) + { + // GUI + background(102); + textSize(12); + text("↑: Zoom up", 120, 6); + text("↓: Zoom down", 120, 20); + text("Enter: Visit Freenove website", 220, 6); + text("Space: Pause", 220, 20); + textSize(16); + // Voltage scale text + for (int i = 5; i >= 0; i--) + { + text(i, 5, 280 - i * 50 - 2); + if (i == 5) + text("V", 15, 280 - i * 50 - 2); + } + // Horizontal line + stroke(64, 64, 64); + for (int i = 0; i < 6; i++) + line(30, 30 + i * 50, width, 30 + i * 50); + // Vertical line time text + text(1000 / hMult + "ms", 40, 15 - 2); + // Vertical line + for (int i = 0; i < (width - 30) / 50 + 1; i++) + line(30 + i * 50, 30, 30 + i * 50, height - 10); + + if (!pause) + { + // Prepare wave data + for (int i = 0; i < analogsCount - 1; i++) + analogs[i] = analogs[i + 1]; + analogs[analogsCount - 1] = height - 10 - analog * (height - 10 - 30) / 255; + // Voltage text + voltage = analog * 500 / 255; + } + String sVoltage = voltage / 100 + "." + voltage / 10 % 10 + voltage % 10; + text(sVoltage + "V", width - 48, 15 - 2); + // Wave line + stroke(0, 255, 0); + for (int i = width; i > 30; i -= hMult * width / analogsCount) + { + int a = i / hMult + width * (hMult - 1) / hMult; + a = a * analogsCount / width - 1; + if (analogs[a] >= 0 && analogs[a - 1] >= 0) + line(i, analogs[a], i - hMult * width / analogsCount, analogs[a - 1]); + } + } + +} + +void keyPressed() +{ + if (key == CODED) + { + if (keyCode == UP) + { + if (hMult == 1) + hMult = 2; + else if (hMult == 2) + hMult = 5; + else if (hMult == 5) + hMult = 10; + } + else if (keyCode == DOWN) + { + if (hMult == 10) + hMult = 5; + else if (hMult == 5) + hMult = 2; + else if (hMult == 2) + hMult = 1; + } + } + else + { + if (key == ' ') + { + pause = !pause; + if (!pause) + { + for (int i = 0; i < analogsCount; i++) + analogs[i] = -1; + } + } + else if (key == '\n' || key == '\r') + { + link("http://www.freenove.com"); + } + } +} \ No newline at end of file diff --git a/Processing/Apps/App_01_1_1_Oscilloscope/PCF8591.pde b/Processing/Apps/App_01_1_1_Oscilloscope/PCF8591.pde new file mode 100644 index 0000000..267a48a --- /dev/null +++ b/Processing/Apps/App_01_1_1_Oscilloscope/PCF8591.pde @@ -0,0 +1,47 @@ +/***************************************************** + * Filename : PCF8591 + * Description : class PCF8591,DAC and ADC + * auther : www.freenove.com + * modification: 2016/08/20 + *****************************************************/ + +class PCF8591 { + private int address; + private I2C i2c; + //constructor,Parameters for the PCF8591 I2C address + public PCF8591(int addr) { + address = addr; + i2c = new I2C(I2C.list()[0]); + } + //Read the ADC value of one channel + public int analogRead(int chn) { + int result = 0; + i2c.beginTransmission(address); + constrain(chn, 0, 3); + i2c.write(0x40 | chn); + try { + byte[] in = i2c.read(1); + result = in[0]&0xff; + } + catch(Exception e) { + println(e); + } + i2c.endTransmission(); + return result; + } + //Read the ADC value of all channels + public byte[] analogRead() { + i2c.beginTransmission(address); + i2c.write(0x44); + i2c.endTransmission(); + byte[] in = i2c.read(4); + return in; + } + //Write the DACvalue + public void analogWrite(int data) { + i2c.beginTransmission(address); + i2c.write(0x40); + i2c.write(data); + i2c.endTransmission(); + } +} \ No newline at end of file diff --git a/Processing/Apps/App_02_1_1_Ellipse/App_02_1_1_Ellipse.pde b/Processing/Apps/App_02_1_1_Ellipse/App_02_1_1_Ellipse.pde new file mode 100644 index 0000000..e64901e --- /dev/null +++ b/Processing/Apps/App_02_1_1_Ellipse/App_02_1_1_Ellipse.pde @@ -0,0 +1,64 @@ +/******************************************************************************* //<>// + * Sketch App_02_1_1_Ellipse + * Author Freenove (http://www.freenove.com) + * Date 2016/08/26 + ****************************************************************************** + * Brief + * This sketch is used to control a 2D ellipse + ****************************************************************************** + * Copyright + * Copyright © Freenove (http://www.freenove.com) + * License + * Creative Commons Attribution ShareAlike 3.0 + * (http://creativecommons.org/licenses/by-sa/3.0/legalcode) + ****************************************************************************** + */ +import processing.io.*; +PCF8591 pcf = new PCF8591(0x48); +void setup() +{ + size(360, 360); + background(102); + textAlign(CENTER, CENTER); + textSize(64); + text("Starting...", width / 2, (height - 40) / 2); + textSize(16); + text("www.freenove.com", width / 2, height - 20); +} + +void draw() +{ + int[] analogs = new int[2]; + analogs[0] = pcf.analogRead(0); + analogs[1] = pcf.analogRead(1); + if (analogs != null) + { + background(102); + drawEllipse(analogs[0], analogs[1]); + } +} + +void drawEllipse(int x, int y) +{ + int maxDiameter = 280; + + fill(255, 255, 255); + textAlign(CENTER, CENTER); + textSize(16); + text("Press Enter to visit www.freenove.com", width / 2, height - 20); + text("X: " + x, width / 2 - 30, 20); + text("Y: " + y, width / 2 + 30, 20); + + x = x * maxDiameter / 255; + y = y * maxDiameter / 255; + fill(227, 118, 12); + ellipse(width / 2, height / 2, x, y); +} + +void keyPressed() +{ + if (key == '\n' || key == '\r') + { + link("http://www.freenove.com"); + } +} \ No newline at end of file diff --git a/Processing/Apps/App_02_1_1_Ellipse/PCF8591.pde b/Processing/Apps/App_02_1_1_Ellipse/PCF8591.pde new file mode 100644 index 0000000..267a48a --- /dev/null +++ b/Processing/Apps/App_02_1_1_Ellipse/PCF8591.pde @@ -0,0 +1,47 @@ +/***************************************************** + * Filename : PCF8591 + * Description : class PCF8591,DAC and ADC + * auther : www.freenove.com + * modification: 2016/08/20 + *****************************************************/ + +class PCF8591 { + private int address; + private I2C i2c; + //constructor,Parameters for the PCF8591 I2C address + public PCF8591(int addr) { + address = addr; + i2c = new I2C(I2C.list()[0]); + } + //Read the ADC value of one channel + public int analogRead(int chn) { + int result = 0; + i2c.beginTransmission(address); + constrain(chn, 0, 3); + i2c.write(0x40 | chn); + try { + byte[] in = i2c.read(1); + result = in[0]&0xff; + } + catch(Exception e) { + println(e); + } + i2c.endTransmission(); + return result; + } + //Read the ADC value of all channels + public byte[] analogRead() { + i2c.beginTransmission(address); + i2c.write(0x44); + i2c.endTransmission(); + byte[] in = i2c.read(4); + return in; + } + //Write the DACvalue + public void analogWrite(int data) { + i2c.beginTransmission(address); + i2c.write(0x40); + i2c.write(data); + i2c.endTransmission(); + } +} \ No newline at end of file diff --git a/Processing/Apps/App_03_1_1_Pong_Game/App_03_1_1_Pong_Game.pde b/Processing/Apps/App_03_1_1_Pong_Game/App_03_1_1_Pong_Game.pde new file mode 100644 index 0000000..9aecac2 --- /dev/null +++ b/Processing/Apps/App_03_1_1_Pong_Game/App_03_1_1_Pong_Game.pde @@ -0,0 +1,172 @@ +/* + ****************************************************************************** + * Sketch App_03_1_1_Pong_Game + * Author Freenove (http://www.freenove.com) + * Date 2016/08/26 + ****************************************************************************** + * Brief + * This sketch is used to play pong game + ****************************************************************************** + * Copyright + * Copyright © Freenove (http://www.freenove.com) + * License + * Creative Commons Attribution ShareAlike 3.0 + * (http://creativecommons.org/licenses/by-sa/3.0/legalcode) + ****************************************************************************** + */ +import processing.io.*; + +PCF8591 pcf = new PCF8591(0x48); + +int winScore = 3; +float acceleration = 0.5; +float deviate = 1; +/* Private variables ---------------------------------------------------------*/ + +Ball ball; +Paddle lPaddle, rPaddle; +int gameState = GameState.WELCOME; +int lScore, rScore; + +void setup() { + size(640, 360); + background(102); + textAlign(CENTER, CENTER); + textSize(64); + text("Starting...", width / 2, (height - 40) / 2); + textSize(16); + text("www.freenove.com", width / 2, height - 20); + + ball = new Ball(10); + lPaddle = new Paddle(new Size(12, 80), 12); + rPaddle = new Paddle(new Size(12, 80), width - 12); + +} + +void draw() { + int[] analogs = new int[2]; + analogs[0] = pcf.analogRead(0); + analogs[1] = pcf.analogRead(1); + if (analogs != null) + { + lPaddle.position.y = analogs[0] * height /255; + rPaddle.position.y = analogs[1] * height /255; + } + + background(102); + if (gameState == GameState.WELCOME) + { + showGUI(); + lPaddle.display(); + rPaddle.display(); + showInfo("Pong Game"); + } + else if (gameState == GameState.PLAYING) + { + ball.updata(); + calculateGame(); + showGUI(); + ball.display(); + lPaddle.display(); + rPaddle.display(); + } + else if (gameState == GameState.PLAYER1WIN) + { + showGUI(); + lPaddle.display(); + rPaddle.display(); + showInfo("Player 1 win!"); + } + else if (gameState == GameState.PLAYER2WIN) + { + showGUI(); + lPaddle.display(); + rPaddle.display(); + showInfo("Player 2 win!"); + } + +} + +void showInfo(String info) +{ + rectMode(CENTER); + stroke(0, 0, 0); + fill(0, 0, 0, 50); + rect(width / 2, height / 2, width / 2, height / 3); + fill(255, 255, 255); + textSize(24); + textAlign(CENTER, CENTER); + text(info, width / 2, height / 2 - 24); + text("Press Space to start", width / 2, height / 2 + 24); +} + +void calculateGame() +{ + if (ball.position.x - ball.radius < lPaddle.position.x + lPaddle.size.width / 2) + { + if (ball.position.y < lPaddle.position.y - lPaddle.size.height / 2 - ball.radius|| + ball.position.y > lPaddle.position.y + lPaddle.size.height / 2 + ball.radius) + { + rScore++; + ball.reset(); + } + else + { + ball.speed.getSpeed(); + ball.speed.speed += acceleration; + ball.speed.getXYSpeed((ball.position.y - lPaddle.position.y) / (lPaddle.size.height / 2) * deviate); + } + } + + if (ball.position.x + ball.radius > rPaddle.position.x - rPaddle.size.width / 2) + { + if (ball.position.y < rPaddle.position.y - rPaddle.size.height / 2 - ball.radius|| + ball.position.y > rPaddle.position.y + rPaddle.size.height / 2 + ball.radius) + { + lScore++; + ball.reset(); + } + else + { + ball.speed.getSpeed(); + ball.speed.speed += acceleration; + ball.speed.getXYSpeed((ball.position.y - rPaddle.position.y) / (rPaddle.size.height / 2) * deviate); + ball.speed.x = - ball.speed.x; + } + } + + if (lScore == winScore) + gameState = GameState.PLAYER1WIN; + if (rScore == winScore) + gameState = GameState.PLAYER2WIN; +} + +void showGUI() +{ + fill(255, 255, 255); + textSize(16); + textAlign(CENTER, CENTER); + text("Press Enter to visit www.freenove.com", width / 4, height - 20); + text("Press Space to restart game", width * 3 / 4, height - 20); + text("Player 1: " + lScore, width / 4, 20); + text("Player 2: " + rScore, width * 3 / 4, 20); + + rectMode(CENTER); + noStroke(); + fill(144, 144, 144); + rect(width / 2, height / 2, 4, height); +} + +void keyPressed() { + if (key == '\n' || key == '\r') + { + link("http://www.freenove.com"); + } + else if (key == ' ') + { + lScore = 0; + rScore = 0; + ball.reset(); + gameState = GameState.PLAYING; + } +} \ No newline at end of file diff --git a/Processing/Apps/App_03_1_1_Pong_Game/Ball.pde b/Processing/Apps/App_03_1_1_Pong_Game/Ball.pde new file mode 100644 index 0000000..ac137a3 --- /dev/null +++ b/Processing/Apps/App_03_1_1_Pong_Game/Ball.pde @@ -0,0 +1,57 @@ +/* + ******************************************************************************* + * Class Ball + * Author Ethan Pan @ Freenove (http://www.freenove.com) + * Date 2016/7/22 + ******************************************************************************* + * Brief + * This class is for pong game. + ******************************************************************************* + * Copyright + * Copyright © Freenove (http://www.freenove.com) + * License + * Creative Commons Attribution ShareAlike 3.0 + * (http://creativecommons.org/licenses/by-sa/3.0/legalcode) + ******************************************************************************* + */ + +/* + * Brief This class is for ball + *****************************************************************************/ +class Ball { + Point position = new Point(); + Speed speed = new Speed(); + int radius; + float initialSpeed = 1; + + Ball(int Radius) + { + radius = Radius; + reset(); + } + + void updata() + { + position.x += speed.x; + position.y += speed.y; + + if (position.y < radius || position.y > height - radius) + speed.y = -speed.y; + } + + void reset() + { + position.x = width / 2; + position.y = height / 2; + speed.x = (random(-1, 1) > 0 ? 1 : -1) * initialSpeed; + speed.y = 0; + } + + void display() + { + ellipseMode(CENTER); + noStroke(); + fill(255, 255, 255); + ellipse(position.x, position.y, 2 * radius, 2 * radius); + } +} \ No newline at end of file diff --git a/Processing/Apps/App_03_1_1_Pong_Game/BasicClass.pde b/Processing/Apps/App_03_1_1_Pong_Game/BasicClass.pde new file mode 100644 index 0000000..ff0bbff --- /dev/null +++ b/Processing/Apps/App_03_1_1_Pong_Game/BasicClass.pde @@ -0,0 +1,94 @@ +/* + ******************************************************************************* + * Class BasicClass + * Author Ethan Pan @ Freenove (http://www.freenove.com) + * Date 2016/8/6 + ******************************************************************************* + * Brief + * These basic classes are for pong game. + ******************************************************************************* + * Copyright + * Copyright © Freenove (http://www.freenove.com) + * License + * Creative Commons Attribution ShareAlike 3.0 + * (http://creativecommons.org/licenses/by-sa/3.0/legalcode) + ******************************************************************************* + */ + +/* + * Brief This class is used to save a point + *****************************************************************************/ +class Point +{ + float x = 0; + float y = 0; + + Point() { + } + + Point(float X, float Y) + { + x = X; + y = Y; + } +} + +/* + * Brief This class is used to save a size + *****************************************************************************/ +class Size +{ + int width = 0; + int height = 0; + + Size() { + } + + Size(int Width, int Height) + { + width = Width; + height = Height; + } +} + +/* + * Brief This class is used to save a 2D speed + *****************************************************************************/ +class Speed +{ + float x = 0; + float y = 0; + float speed; + + void getSpeed() + { + speed = sqrt(sq(x) + sq(y)); + } + + void getXYSpeed(float degree) + { + x = speed * cos(degree); + y = speed * sin(degree); + } + + Speed() { + } + + Speed(float X, float Y) + { + x = X; + y = Y; + } +} + +/* + * Brief This enum is used to save a gameState + *****************************************************************************/ +class GameState +{ + final static int WELCOME = 0; + final static int PLAYING = 1; + final static int PLAYER1WIN = 2; + final static int PLAYER2WIN = 3; +} + diff --git a/Processing/Apps/App_03_1_1_Pong_Game/PCF8591.pde b/Processing/Apps/App_03_1_1_Pong_Game/PCF8591.pde new file mode 100644 index 0000000..267a48a --- /dev/null +++ b/Processing/Apps/App_03_1_1_Pong_Game/PCF8591.pde @@ -0,0 +1,47 @@ +/***************************************************** + * Filename : PCF8591 + * Description : class PCF8591,DAC and ADC + * auther : www.freenove.com + * modification: 2016/08/20 + *****************************************************/ + +class PCF8591 { + private int address; + private I2C i2c; + //constructor,Parameters for the PCF8591 I2C address + public PCF8591(int addr) { + address = addr; + i2c = new I2C(I2C.list()[0]); + } + //Read the ADC value of one channel + public int analogRead(int chn) { + int result = 0; + i2c.beginTransmission(address); + constrain(chn, 0, 3); + i2c.write(0x40 | chn); + try { + byte[] in = i2c.read(1); + result = in[0]&0xff; + } + catch(Exception e) { + println(e); + } + i2c.endTransmission(); + return result; + } + //Read the ADC value of all channels + public byte[] analogRead() { + i2c.beginTransmission(address); + i2c.write(0x44); + i2c.endTransmission(); + byte[] in = i2c.read(4); + return in; + } + //Write the DACvalue + public void analogWrite(int data) { + i2c.beginTransmission(address); + i2c.write(0x40); + i2c.write(data); + i2c.endTransmission(); + } +} \ No newline at end of file diff --git a/Processing/Apps/App_03_1_1_Pong_Game/Paddle.pde b/Processing/Apps/App_03_1_1_Pong_Game/Paddle.pde new file mode 100644 index 0000000..a86ff51 --- /dev/null +++ b/Processing/Apps/App_03_1_1_Pong_Game/Paddle.pde @@ -0,0 +1,44 @@ +/* + ******************************************************************************* + * Class Paddle + * Author Ethan Pan @ Freenove (http://www.freenove.com) + * Date 2016/7/22 + ******************************************************************************* + * Brief + * This class is for pong game. + ******************************************************************************* + * Copyright + * Copyright © Freenove (http://www.freenove.com) + * License + * Creative Commons Attribution ShareAlike 3.0 + * (http://creativecommons.org/licenses/by-sa/3.0/legalcode) + ******************************************************************************* + */ + +/* + * Brief This class is for paddle + *****************************************************************************/ +class Paddle { + Point position = new Point(); + Size size; + + Paddle(Size paddleSize, int xPosition) + { + size = paddleSize; + position.x = xPosition; + position.y = height / 2; + } + + void moveTo(int yPosition) + { + position.y = yPosition; + } + + void display() + { + rectMode(CENTER); + noStroke(); + fill(255, 255, 255); + rect(position.x, position.y, size.width, size.height); + } +} \ No newline at end of file diff --git a/Processing/Apps/App_04_1_1_Snake_Game/App_04_1_1_Snake_Game.pde b/Processing/Apps/App_04_1_1_Snake_Game/App_04_1_1_Snake_Game.pde new file mode 100644 index 0000000..b1fa227 --- /dev/null +++ b/Processing/Apps/App_04_1_1_Snake_Game/App_04_1_1_Snake_Game.pde @@ -0,0 +1,164 @@ +/* + ****************************************************************************** + * Sketch App_04_1_1_Snake_Game + * Author Freenove (http://www.freenove.com) + * Date 2016/08/27 + ****************************************************************************** + * Brief + * This sketch is used to play snake game + ****************************************************************************** + * Copyright + * Copyright © Freenove (http://www.freenove.com) + * License + * Creative Commons Attribution ShareAlike 3.0 + * (http://creativecommons.org/licenses/by-sa/3.0/legalcode) + ****************************************************************************** + */ +import processing.io.*; +int threshold = 400; + +KeyPad keyUp = new KeyPad(23); +KeyPad keyDown = new KeyPad(17); +KeyPad keyLeft = new KeyPad(22); +KeyPad keyRight = new KeyPad(18); + +Snake snake; +Food food; + +void setup() { + print("Starting ... \n"); + size(640, 360); + background(102); + textAlign(CENTER, CENTER); + textSize(64); + text("Starting...", width / 2, (height - 40) / 2); + textSize(16); + text("www.freenove.com", width / 2, height - 20); + + food = new Food(new GridMap(new Size(width, height), 20, 2)); + snake = new Snake(new GridMap(new Size(width, height), 20, 2)); + thread("keypadDetect"); +} + +void draw() { + background(102); + if (snake.gameState == GameState.WELCOME) + { + rectMode(CENTER); + stroke(0, 0, 0); + fill(0, 0, 0, 50); + rect(width / 2, height / 2, width / 2, height / 3); + fill(255, 255, 255); + textSize(24); + textAlign(CENTER, CENTER); + text("Snake Game", width / 2, height / 2 - 24); + text("Press Space to start", width / 2, height / 2 + 24); + } else if (snake.gameState == GameState.PLAYING) + { + + if (snake.body[0].x == food.position.x && snake.body[0].y == food.position.y) + { + snake.grow(); + food.generate(snake.body, snake.length); + snake.speedUp(); + } + snake.step(); + showGame(); + } else if (snake.gameState == GameState.LOSE) + { + showGame(); + rectMode(CENTER); + stroke(0, 0, 0); + fill(0, 0, 0, 50); + rect(width / 2, height / 2, width / 2, height / 3); + fill(255, 255, 255); + textSize(24); + textAlign(CENTER, CENTER); + text("You lose!", width / 2, height / 2 - 24); + text("Press Space to start", width / 2, height / 2 + 24); + } +} + +void showGame() +{ + snake.display(); + food.display(); + + fill(255, 255, 255); + textSize(16); + textAlign(LEFT, CENTER); + text("Press Enter to visit www.freenove.com", 20, height - 20); + textAlign(RIGHT, CENTER); + text("Press Space to restart game", width - 20, height - 20); + textAlign(LEFT, CENTER); + text("Score: " + (snake.length - 3), 20, 20); + textAlign(RIGHT, CENTER); + text("Speed: " + ((snake.initSpeed - snake.speed) / 5 + 1), width - 20, 20); +} + +void keyPressed() { + if ((key == CODED) || (keyValue != -1)) + { + if ((keyCode == UP) ||((keyValue == keyUp.pin))) + { + if (snake.direction != Direction.DOWN) + snake.nextDirection = Direction.UP; + } else if ((keyCode == DOWN)||((keyValue == keyDown.pin))) { + if (snake.direction != Direction.UP) + snake.nextDirection = Direction.DOWN; + } else if ((keyCode == LEFT)||((keyValue == keyLeft.pin))) { + if (snake.direction != Direction.RIGHT) + snake.nextDirection = Direction.LEFT; + } else if ((keyCode == RIGHT)||((keyValue == keyRight.pin))) { + if (snake.direction != Direction.LEFT) + snake.nextDirection = Direction.RIGHT; + } + //keyValue = -1; + println(keyValue); + } else + { + if (key == '\n' || key == '\r') + { + link("http://www.freenove.com"); + } else if (key == ' ') + { + snake.reset(); + food.generate(snake.body, snake.length); + snake.gameState = GameState.PLAYING; + } + } +} +void keypadDetect() { + while (true) { + keyUp.keyScan(); + keyDown.keyScan(); + keyLeft.keyScan(); + keyRight.keyScan(); + transAction(); + try { + Thread.sleep(10); + } + catch(Exception e) { + } + } +} +void transAction() { + if ((keyValue != -1)) + { + if (keyValue == keyUp.pin) + { + if (snake.direction != Direction.DOWN) + snake.nextDirection = Direction.UP; + } else if (((keyValue == keyDown.pin))) { + if (snake.direction != Direction.UP) + snake.nextDirection = Direction.DOWN; + } else if (((keyValue == keyLeft.pin))) { + if (snake.direction != Direction.RIGHT) + snake.nextDirection = Direction.LEFT; + } else if (((keyValue == keyRight.pin))) { + if (snake.direction != Direction.LEFT) + snake.nextDirection = Direction.RIGHT; + } + keyValue = -1; + } +} \ No newline at end of file diff --git a/Processing/Apps/App_04_1_1_Snake_Game/BasicClass.pde b/Processing/Apps/App_04_1_1_Snake_Game/BasicClass.pde new file mode 100644 index 0000000..2e21abb --- /dev/null +++ b/Processing/Apps/App_04_1_1_Snake_Game/BasicClass.pde @@ -0,0 +1,120 @@ +/* + ******************************************************************************* + * Class BasicClass + * Author Ethan Pan @ Freenove (http://www.freenove.com) + * Date 2016/8/6 + ******************************************************************************* + * Brief + * These basic classes are for snake game. + ******************************************************************************* + * Copyright + * Copyright © Freenove (http://www.freenove.com) + * License + * Creative Commons Attribution ShareAlike 3.0 + * (http://creativecommons.org/licenses/by-sa/3.0/legalcode) + ******************************************************************************* + */ + +/* + * Brief This class is used to save a point + *****************************************************************************/ +class Point +{ + int x = 0; + int y = 0; + + Point() { + } + + Point(int X, int Y) + { + x = X; + y = Y; + } +} + +/* + * Brief This class is used to save a size + *****************************************************************************/ +class Size +{ + int width = 0; + int height = 0; + + Size() { + } + + Size(int Width, int Height) + { + width = Width; + height = Height; + } +} + +/* + * Brief This enum is used to save a direction + *****************************************************************************/ +class Direction +{ + final static int UP = 0; + final static int DOWN = 1; + final static int LEFT = 2; + final static int RIGHT = 3; +} + +/* + * Brief This enum is used to save a gameState + *****************************************************************************/ +class GameState +{ + final static int WELCOME = 0; + final static int PLAYING = 1; + final static int WIN = 2; + final static int LOSE = 3; +} + +/* + * Brief This enum is used to save a grid map + *****************************************************************************/ +class GridMap +{ + Size mapSize; + Size gripSize; + int gridLength; + int blockGap; + int blockLength; + + GridMap() { + } + + GridMap(Size MapSize, int GridLength, int BlockGap) + { + mapSize = MapSize; + gridLength = GridLength; + gripSize = new Size(mapSize.width / gridLength, mapSize.height / gridLength); + blockGap = BlockGap; + blockLength = gridLength - blockGap; + } + + Point getGripPoint(Point mapPoint) + { + Point point = new Point(); + point.x = mapPoint.x / gridLength; + point.y = mapPoint.y / gridLength; + return point; + } + + Point getMapPoint(Point gripPoint) + { + Point point = new Point(); + point.x = gripPoint.x * gridLength + gridLength / 2; + point.y = gripPoint.y * gridLength + gridLength / 2; + return point; + } + + void adjustMapPoint(Point mapPoint) + { + mapPoint.x = mapPoint.x / gridLength * gridLength + gridLength / 2; + mapPoint.y = mapPoint.y / gridLength * gridLength + gridLength / 2; + } +} diff --git a/Processing/Apps/App_04_1_1_Snake_Game/Food.pde b/Processing/Apps/App_04_1_1_Snake_Game/Food.pde new file mode 100644 index 0000000..d64f2e2 --- /dev/null +++ b/Processing/Apps/App_04_1_1_Snake_Game/Food.pde @@ -0,0 +1,61 @@ +/* + ******************************************************************************* + * Class Food + * Author Ethan Pan @ Freenove (http://www.freenove.com) + * Date 2016/7/20 + ******************************************************************************* + * Brief + * This class is for snake game. + ******************************************************************************* + * Copyright + * Copyright © Freenove (http://www.freenove.com) + * License + * Creative Commons Attribution ShareAlike 3.0 + * (http://creativecommons.org/licenses/by-sa/3.0/legalcode) + ******************************************************************************* + */ + +/* + * Brief This class is for food + *****************************************************************************/ +class Food { + Point position; + GridMap map; + + Food(GridMap gridMap) + { + map = gridMap; + } + + void generate(Point[] exclude, int length) + { + Point point = new Point(); + boolean isGenerating = true; + + while (isGenerating) + { + point.x = (int)random(0, map.gripSize.width - 1); + point.y = (int)random(0, map.gripSize.height - 1); + + isGenerating = false; + if (exclude != null) + { + for (int i = 0; i < length; i++) + { + if (point.x == exclude[i].x && point.y == exclude[i].y) + isGenerating = true; + } + } + } + position = point; + } + + void display() + { + rectMode(CENTER); + noStroke(); + fill(0, 255, 0); + Point mapPosition = map.getMapPoint(position); + rect(mapPosition.x, mapPosition.y, map.blockLength, map.blockLength); + } +} \ No newline at end of file diff --git a/Processing/Apps/App_04_1_1_Snake_Game/KeyPad.pde b/Processing/Apps/App_04_1_1_Snake_Game/KeyPad.pde new file mode 100644 index 0000000..62c17a0 --- /dev/null +++ b/Processing/Apps/App_04_1_1_Snake_Game/KeyPad.pde @@ -0,0 +1,90 @@ +/* + ****************************************************************************** + * class Keypad + * Author Freenove (http://www.freenove.com) + * Date 2016/08/27 + ****************************************************************************** + * Brief + * This class is used to get a single button key value (GPIO numbering) + ****************************************************************************** + * Copyright + * Copyright © Freenove (http://www.freenove.com) + * License + * Creative Commons Attribution ShareAlike 3.0 + * (http://creativecommons.org/licenses/by-sa/3.0/legalcode) + ****************************************************************************** + */ +int keyValue = -1; +class KeyPad +{ + final int IDLE = 0, + PRESSED = 1, + HOLD = 2, + RELEASED = 3; + int btnState = IDLE; + long holdTimer = 0; + final int holdTime = 500; + boolean changeState = false; + int lastButtonIOState = GPIO.HIGH; + int buttonIOState=GPIO.HIGH; + int nowButtonState; + boolean buttonChanged = false; + int lastChangeTime; + int decounceTime = 50; + int pin; + public KeyPad(int Pin) { + pin = Pin; + GPIO.pinMode(pin, GPIO.INPUT); + } + + void keyScan() { + nowButtonState =GPIO.digitalRead(pin); + if (nowButtonState != lastButtonIOState) { + lastChangeTime = millis(); + } + if (millis() - lastChangeTime > decounceTime) { + if (buttonIOState != nowButtonState) { + buttonIOState = nowButtonState; + changeState = true; + if (buttonIOState == GPIO.LOW) { + //btnState = PRESSED; + //keyValue = pin; + //println("Key is Pressed !! "); + } else if (buttonIOState == GPIO.HIGH) { + //println("Key is Released !! "); + } + } + } + switch(btnState) { + case IDLE: + if (changeState) { + changeState = false; + btnState = PRESSED; + holdTimer = millis(); + keyValue = pin; + } + break; + case PRESSED: + if (millis() - holdTimer > holdTime) { + btnState = HOLD; + keyValue = pin; + }else if(changeState){ + changeState = false; + btnState = RELEASED; + } + break; + case HOLD: + keyValue = pin; + if (changeState) { + changeState = false; + btnState = RELEASED; + } + break; + case RELEASED: + keyValue = -1; + btnState = IDLE; + break; + } + lastButtonIOState = nowButtonState; + } +} \ No newline at end of file diff --git a/Processing/Apps/App_04_1_1_Snake_Game/Snake.pde b/Processing/Apps/App_04_1_1_Snake_Game/Snake.pde new file mode 100644 index 0000000..5639691 --- /dev/null +++ b/Processing/Apps/App_04_1_1_Snake_Game/Snake.pde @@ -0,0 +1,115 @@ +/* + ******************************************************************************* + * Class Snake + * Author Ethan Pan @ Freenove (http://www.freenove.com) + * Date 2016/8/6 + ******************************************************************************* + * Brief + * This class is for snake game. + ******************************************************************************* + * Copyright + * Copyright © Freenove (http://www.freenove.com) + * License + * Creative Commons Attribution ShareAlike 3.0 + * (http://creativecommons.org/licenses/by-sa/3.0/legalcode) + ******************************************************************************* + */ + +/* + * Brief This class is for snake + *****************************************************************************/ +class Snake { + GridMap map; + + int length; + final int initSpeed = 150; + int speed; + int stepCounter; + int direction; + int nextDirection; + Point[] body; + + int gameState = GameState.WELCOME; + + Snake(GridMap gridMap) + { + map = gridMap; + body = new Point[map.gripSize.height * map.gripSize.width]; + reset(); + } + + void reset() + { + length = 3; + speed = initSpeed ; + direction = Direction.UP; + nextDirection = Direction.UP; + body[0] = new Point(map.gripSize.width / 2, map.gripSize.height / 2); + body[1] = new Point(body[0].x, body[0].y + 1); + body[2] = new Point(body[0].x, body[0].y + 2); + } + + void display() + { + rectMode(CENTER); + noStroke(); + fill(227, 118, 12); + for (int i = 0; i < length; i++) + { + Point mapPosition = map.getMapPoint(body[i]); + rect(mapPosition.x, mapPosition.y, map.blockLength, map.blockLength); + } + } + + void speedUp() + { + if (speed > 0) + speed--; + } + + void grow() + { + length++; + } + + void step() + { + if (stepCounter++ % (speed / 5) != 0) + return; + + for (int i = length; i > 0; i--) + body[i] = body[i - 1]; + + direction = nextDirection; + if (direction == Direction.UP) + { + body[0] = new Point(body[1].x, body[1].y - 1); + if (body[0].y < 0) + gameState = GameState.LOSE; + } + else if (direction == Direction.DOWN) + { + body[0] = new Point(body[1].x, body[1].y + 1); + if (body[0].y > map.gripSize.height - 1) + gameState = GameState.LOSE; + } + else if (direction == Direction.LEFT) + { + body[0] = new Point(body[1].x - 1, body[1].y); + if (body[0].x < 0) + gameState = GameState.LOSE; + } + else if (direction == Direction.RIGHT) + { + body[0] = new Point(body[1].x + 1, body[1].y); + if (body[0].x > map.gripSize.width - 1) + gameState = GameState.LOSE; + } + + for (int i = 1; i < length; i++) + { + if (body[0].x == body[i].x && body[0].y == body[i].y) + gameState = GameState.LOSE; + } + } +} \ No newline at end of file diff --git a/Processing/Apps/App_05_1_1_Tetris/App_05_1_1_Tetris.pde b/Processing/Apps/App_05_1_1_Tetris/App_05_1_1_Tetris.pde new file mode 100644 index 0000000..11e9b19 --- /dev/null +++ b/Processing/Apps/App_05_1_1_Tetris/App_05_1_1_Tetris.pde @@ -0,0 +1,156 @@ +/* + ****************************************************************************** + * Sketch App_05_1_1_Tetris + * Author Freenove (http://www.freenove.com) + * Date 2016/08/27 + ****************************************************************************** + * Brief + * This sketch is used to play Tetris game + ****************************************************************************** + * Copyright + * Copyright © Freenove (http://www.freenove.com) + * License + * Creative Commons Attribution ShareAlike 3.0 + * (http://creativecommons.org/licenses/by-sa/3.0/legalcode) + ****************************************************************************** + */ +import processing.io.*; + +static final int w = 10; // 4 +static final int h = 25; // 60 +static final int framesInSecond = 30; +static float gameInitSpeed = 10; +static float gameSpeed = 10; +static final int BlockScale = 15; +static final int sizeWidth = w*BlockScale+100; +static final int sizeHeight = h*BlockScale; + + +KeyPad keyUp = new KeyPad(23); +KeyPad keyDown = new KeyPad(17); +KeyPad keyLeft = new KeyPad(22); +KeyPad keyRight = new KeyPad(18); + +boolean isPaused = false; +boolean keyAllow = true; +float updatingThreshold = 0; +Game game; + +float recalculateUpdatingThreshold(float threshold) { + return threshold + 1; +} +void settings() { + size(sizeWidth, sizeHeight); +} +void setup() { + game = new Game(w, h); + generateRandomBlock(game); + frameRate(framesInSecond); + thread("keypadDetect"); +} + +void draw() { + + background(102); + Game newGame = game; + + updatingThreshold = recalculateUpdatingThreshold(updatingThreshold); + if (updatingThreshold > gameSpeed) { + if (isGameOver(newGame)) { + } else if (isPaused) { + } else { + newGame = updateGameState(game); + } + updatingThreshold = 0; + } + drawGameState(newGame); + if (!isGameOver(newGame)&& (isPaused)) { //pause + textSize(40); + fill(0); + text("Pause", BlockScale*2, 150); + keyAllow = false; + } else if (isGameOver(newGame)&& (isPaused)) { //restart game + game = new Game(w, h); + generateRandomBlock(game); + isPaused = false; + keyAllow = false; + } else if (isGameOver(newGame)) { //game over + textSize(40); + fill(0); + text("Game \nOver", BlockScale*2, 150); + keyAllow = false; + } else { //playing + keyAllow = true; + } + + //level,score information + pushMatrix(); + translate(w*BlockScale, 0); + fill(255); + textSize(20); + text("Level\n"+game.level, 10, BlockScale*7); + text("Scores\n"+game.score, 10, BlockScale*11); + textSize(12); + text("Freenove.com", 10, sizeHeight-30); + drawNextBlock(game.nextBlock, BlockScale*2, BlockScale*1); + popMatrix(); +} + +void keyPressed() { + if (key == CODED) { + if (keyAllow) { + switch (keyCode) { + case LEFT: + moveBlock(game, MoveLeft); + break; + case RIGHT: + moveBlock(game, MoveRight); + break; + case DOWN: + makeBlockFall(game); + break; + case UP: + rotateBlock(game); + break; + } + } + } else if (key == ' ') { // SPACE + isPaused =! isPaused; + } +} +void keypadDetect() { + while (true) { + keyUp.keyScan(); + keyDown.keyScan(); + keyLeft.keyScan(); + keyRight.keyScan(); + transAction(); + try { + Thread.sleep(10); + } + catch(Exception e) { + } + } +} +void transAction() { + if ((keyValue != -1)) + { + if (keyAllow) { + if (keyValue == keyLeft.pin) { + moveBlock(game, MoveLeft); + } else if (keyValue == keyRight.pin) { + moveBlock(game, MoveRight); + } else if (keyValue == keyDown.pin) { + makeBlockFall(game); + } else if (keyValue == keyUp.pin) { + rotateBlock(game); + } + } + try { + Thread.sleep(50); + } + catch(Exception e) { + } + keyValue = -1; + } +} \ No newline at end of file diff --git a/Processing/Apps/App_05_1_1_Tetris/KeyPad.pde b/Processing/Apps/App_05_1_1_Tetris/KeyPad.pde new file mode 100644 index 0000000..62c17a0 --- /dev/null +++ b/Processing/Apps/App_05_1_1_Tetris/KeyPad.pde @@ -0,0 +1,90 @@ +/* + ****************************************************************************** + * class Keypad + * Author Freenove (http://www.freenove.com) + * Date 2016/08/27 + ****************************************************************************** + * Brief + * This class is used to get a single button key value (GPIO numbering) + ****************************************************************************** + * Copyright + * Copyright © Freenove (http://www.freenove.com) + * License + * Creative Commons Attribution ShareAlike 3.0 + * (http://creativecommons.org/licenses/by-sa/3.0/legalcode) + ****************************************************************************** + */ +int keyValue = -1; +class KeyPad +{ + final int IDLE = 0, + PRESSED = 1, + HOLD = 2, + RELEASED = 3; + int btnState = IDLE; + long holdTimer = 0; + final int holdTime = 500; + boolean changeState = false; + int lastButtonIOState = GPIO.HIGH; + int buttonIOState=GPIO.HIGH; + int nowButtonState; + boolean buttonChanged = false; + int lastChangeTime; + int decounceTime = 50; + int pin; + public KeyPad(int Pin) { + pin = Pin; + GPIO.pinMode(pin, GPIO.INPUT); + } + + void keyScan() { + nowButtonState =GPIO.digitalRead(pin); + if (nowButtonState != lastButtonIOState) { + lastChangeTime = millis(); + } + if (millis() - lastChangeTime > decounceTime) { + if (buttonIOState != nowButtonState) { + buttonIOState = nowButtonState; + changeState = true; + if (buttonIOState == GPIO.LOW) { + //btnState = PRESSED; + //keyValue = pin; + //println("Key is Pressed !! "); + } else if (buttonIOState == GPIO.HIGH) { + //println("Key is Released !! "); + } + } + } + switch(btnState) { + case IDLE: + if (changeState) { + changeState = false; + btnState = PRESSED; + holdTimer = millis(); + keyValue = pin; + } + break; + case PRESSED: + if (millis() - holdTimer > holdTime) { + btnState = HOLD; + keyValue = pin; + }else if(changeState){ + changeState = false; + btnState = RELEASED; + } + break; + case HOLD: + keyValue = pin; + if (changeState) { + changeState = false; + btnState = RELEASED; + } + break; + case RELEASED: + keyValue = -1; + btnState = IDLE; + break; + } + lastButtonIOState = nowButtonState; + } +} \ No newline at end of file diff --git a/Processing/Apps/App_05_1_1_Tetris/TetrisBlock.pde b/Processing/Apps/App_05_1_1_Tetris/TetrisBlock.pde new file mode 100644 index 0000000..1b9fc6a --- /dev/null +++ b/Processing/Apps/App_05_1_1_Tetris/TetrisBlock.pde @@ -0,0 +1,42 @@ +// Classic Tetris only blocks +static final int BlockPartsCount = 4; +static final int BlocksCount = 7; +static final int DirectionsCount = 4; + +static final int I = 0; +static final int O = 1; +static final int T = 2; +static final int S = 3; +static final int Z = 4; +static final int J = 5; +static final int L = 6; + +static final int North = 0; +static final int East = 1; +static final int South = 2; +static final int West = 3; + +class BlockPart { + int xPos; + int yPos; + + BlockPart(int blockXPos, int blockYPos) { + xPos = blockXPos; + yPos = blockYPos; + } +}; + +class Block { + int type; + int xPos; + int yPos; + int direction; + BlockPart[] parts; + + Block (int blockType, int blockXPos, int blockYPos, int blockDirection) { + type = blockType; + xPos = blockXPos; + yPos = blockYPos; + direction = blockDirection; + } +}; \ No newline at end of file diff --git a/Processing/Apps/App_05_1_1_Tetris/TetrisBlockConstruct.pde b/Processing/Apps/App_05_1_1_Tetris/TetrisBlockConstruct.pde new file mode 100644 index 0000000..fa0cc02 --- /dev/null +++ b/Processing/Apps/App_05_1_1_Tetris/TetrisBlockConstruct.pde @@ -0,0 +1,159 @@ +BlockPart[] getIBlockParts(int direction) { + BlockPart[] parts = new BlockPart[BlockPartsCount]; + if ((direction == East) || (direction == West)) { + parts[0] = new BlockPart(0,0); + parts[1] = new BlockPart(1,0); + parts[2] = new BlockPart(2,0); + parts[3] = new BlockPart(3,0); + } else { + parts[0] = new BlockPart(0,0); + parts[1] = new BlockPart(0,1); + parts[2] = new BlockPart(0,2); + parts[3] = new BlockPart(0,3); + } + return parts; +} + +BlockPart[] getOBlockParts() { + BlockPart[] parts = new BlockPart[BlockPartsCount]; + parts[0] = new BlockPart(0,0); + parts[1] = new BlockPart(1,0); + parts[2] = new BlockPart(0,1); + parts[3] = new BlockPart(1,1); + return parts; +} + +BlockPart[] getTBlockParts(int direction) { + BlockPart[] parts = new BlockPart[BlockPartsCount]; + switch (direction) { + case East: + parts[0] = new BlockPart(0,0); + parts[1] = new BlockPart(1,0); + parts[2] = new BlockPart(2,0); + parts[3] = new BlockPart(1,1); + break; + case South: + parts[0] = new BlockPart(1,0); + parts[1] = new BlockPart(0,1); + parts[2] = new BlockPart(1,1); + parts[3] = new BlockPart(1,2); + break; + case West: + parts[0] = new BlockPart(1,0); + parts[1] = new BlockPart(0,1); + parts[2] = new BlockPart(1,1); + parts[3] = new BlockPart(2,1); + break; + case North: + parts[0] = new BlockPart(0,0); + parts[1] = new BlockPart(0,1); + parts[2] = new BlockPart(1,1); + parts[3] = new BlockPart(0,2); + break; + } + return parts; +} + +BlockPart[] getSBlockParts(int direction) { + BlockPart[] parts = new BlockPart[BlockPartsCount]; + switch (direction) { + case East: + case West: + parts[0] = new BlockPart(0,0); + parts[1] = new BlockPart(0,1); + parts[2] = new BlockPart(1,1); + parts[3] = new BlockPart(1,2); + break; + case South: + case North: + parts[0] = new BlockPart(0,1); + parts[1] = new BlockPart(1,0); + parts[2] = new BlockPart(1,1); + parts[3] = new BlockPart(2,0); + break; + } + return parts; +} + +BlockPart[] getZBlockParts(int direction) { + BlockPart[] parts = new BlockPart[BlockPartsCount]; + switch (direction) { + case East: + case West: + parts[0] = new BlockPart(1,0); + parts[1] = new BlockPart(0,1); + parts[2] = new BlockPart(1,1); + parts[3] = new BlockPart(0,2); + break; + case South: + case North: + parts[0] = new BlockPart(0,0); + parts[1] = new BlockPart(1,0); + parts[2] = new BlockPart(1,1); + parts[3] = new BlockPart(2,1); + break; + } + return parts; +} + +BlockPart[] getJBlockParts(int direction) { + BlockPart[] parts = new BlockPart[BlockPartsCount]; + switch (direction) { + case East: + parts[0] = new BlockPart(1,0); + parts[1] = new BlockPart(1,1); + parts[2] = new BlockPart(0,2); + parts[3] = new BlockPart(1,2); + break; + case South: + parts[0] = new BlockPart(0,0); + parts[1] = new BlockPart(0,1); + parts[2] = new BlockPart(1,1); + parts[3] = new BlockPart(2,1); + break; + case West: + parts[0] = new BlockPart(0,0); + parts[1] = new BlockPart(1,0); + parts[2] = new BlockPart(0,1); + parts[3] = new BlockPart(0,2); + break; + case North: + parts[0] = new BlockPart(0,0); + parts[1] = new BlockPart(1,0); + parts[2] = new BlockPart(2,0); + parts[3] = new BlockPart(2,1); + break; + } + return parts; +} + +BlockPart[] getLBlockParts(int direction) { + BlockPart[] parts = new BlockPart[BlockPartsCount]; + switch (direction) { + case East: + parts[0] = new BlockPart(0,0); + parts[1] = new BlockPart(0,1); + parts[2] = new BlockPart(0,2); + parts[3] = new BlockPart(1,2); + break; + case South: + parts[0] = new BlockPart(0,0); + parts[1] = new BlockPart(0,1); + parts[2] = new BlockPart(1,0); + parts[3] = new BlockPart(2,0); + break; + case West: + parts[0] = new BlockPart(0,0); + parts[1] = new BlockPart(1,0); + parts[2] = new BlockPart(1,1); + parts[3] = new BlockPart(1,2); + break; + case North: + parts[0] = new BlockPart(0,1); + parts[1] = new BlockPart(1,1); + parts[2] = new BlockPart(2,0); + parts[3] = new BlockPart(2,1); + break; + } + return parts; +} \ No newline at end of file diff --git a/Processing/Apps/App_05_1_1_Tetris/TetrisBlockProcess.pde b/Processing/Apps/App_05_1_1_Tetris/TetrisBlockProcess.pde new file mode 100644 index 0000000..0dfdb3a --- /dev/null +++ b/Processing/Apps/App_05_1_1_Tetris/TetrisBlockProcess.pde @@ -0,0 +1,64 @@ + + +BlockPart[] getBlockParts(Block block) { + switch(block.type) { + case I: return getIBlockParts(block.direction); + case O: return getOBlockParts(); + case T: return getTBlockParts(block.direction); + case S: return getSBlockParts(block.direction); + case Z: return getZBlockParts(block.direction); + case J: return getJBlockParts(block.direction); + case L: return getLBlockParts(block.direction); + } + + return getIBlockParts(block.direction); +} + +void makeBlockFall(Block block) { + block.yPos += 1; + for (int i = 0; i < BlockPartsCount; i++) { + block.parts[i].yPos += 1; + } +} + +// We assume, only unsigned int is possible in block parts[i].xPos. +void arrangeNewBlock(Block block, int wellWidth) { + + int leftXShift = 0; + int maxYShift = 0; + for (int i = 0; i < BlockPartsCount; i++) { + + maxYShift = max (block.parts[i].yPos, maxYShift); + + block.parts[i].xPos = block.parts[i].xPos + block.xPos; + block.parts[i].yPos = block.parts[i].yPos + block.yPos; + + if (block.parts[i].xPos >= wellWidth) + leftXShift = max(leftXShift, block.parts[i].xPos + 1 - wellWidth); + } + + for (int i = 0; i < BlockPartsCount; i++) { + block.parts[i].xPos = block.parts[i].xPos - leftXShift; + block.parts[i].yPos = block.parts[i].yPos - (1 + maxYShift); + } +} + +Block createBlock(int type, int direction, int xPos, int yPos, int wellWidth) { + Block block = new Block(type, xPos, yPos, direction); + block.parts = getBlockParts(block); + arrangeNewBlock(block, wellWidth); + return block; +} + +void moveBlockHorizontal(Block block, int distance) { + for (int i = 0; i < BlockPartsCount; i++) { + block.parts[i].xPos = block.parts[i].xPos + distance; + } + block.xPos += distance; +} + +int rotateDirection(int prevDirection) { + if (prevDirection < DirectionsCount - 1) + return prevDirection + 1; + return 0; +} \ No newline at end of file diff --git a/Processing/Apps/App_05_1_1_Tetris/TetrisGame.pde b/Processing/Apps/App_05_1_1_Tetris/TetrisGame.pde new file mode 100644 index 0000000..b105585 --- /dev/null +++ b/Processing/Apps/App_05_1_1_Tetris/TetrisGame.pde @@ -0,0 +1,23 @@ + +class Game { + int wellWidth; + int wellHeight; + int score; + int level; + boolean[][] blocks; + Block fallingBlock; + Block nextBlock; + boolean erasingNeeded; + + Game (int w, int h) { + wellWidth = w; + wellHeight = h; + fallingBlock = null; + erasingNeeded = false; + + blocks = new boolean[w][h]; + for (int x = 0; x < w; x++) + for (int y = 0; y < h; y++) + blocks[x][y] = false; + } +}; \ No newline at end of file diff --git a/Processing/Apps/App_05_1_1_Tetris/TetrisGameState.pde b/Processing/Apps/App_05_1_1_Tetris/TetrisGameState.pde new file mode 100644 index 0000000..e2dbac5 --- /dev/null +++ b/Processing/Apps/App_05_1_1_Tetris/TetrisGameState.pde @@ -0,0 +1,160 @@ +static final int MoveLeft = -1; +static final int MoveRight = 1; + +boolean isBlockStuck(Game game) +{ + Block block = game.fallingBlock; + if (block == null) + return false; + + boolean[][] blocks = game.blocks; + BlockPart[] parts = block.parts; + + boolean stuck = false; + for (int i = 0; (i < BlockPartsCount) && (!stuck); i++) { + if (parts[i].xPos >= 0 && parts[i].yPos >= 0) + stuck = stuck + || parts[i].yPos + 1 >= game.wellHeight + || blocks[parts[i].xPos][parts[i].yPos + 1]; + } + + return stuck; +} + +void fixateBlock(Game game) { + Block block = game.fallingBlock; + if (block == null) + return; + + BlockPart[] parts = block.parts; + + for (int i = 0; i < BlockPartsCount; i++) { + if (parts[i].yPos >= 0) + game.blocks[parts[i].xPos][parts[i].yPos] = true; + } + + game.fallingBlock = null; +} + +void eraseFilledLines(Game game) { + int eraseRows=0; + for (int y = game.wellHeight - 1; y >= 0; ) { + + boolean erasable = true; + for (int x = 0; x < game.wellWidth; x++) + erasable = erasable && game.blocks[x][y]; + + if (erasable) { + eraseRows +=1; + // Move blocks down + for (int y2 = y - 1; y2 >= 0; y2--) + for (int x = 0; x < game.wellWidth; x++) + game.blocks[x][y2 + 1] = game.blocks[x][y2]; + + // Top level needs to be cleared. + for (int x = 0; x < game.wellWidth; x++) + game.blocks[x][0] = false; + } else { + y--; + } + } + if (eraseRows != 0) { + game.score+=10*(eraseRows*2-1); + eraseRows=0; + game.level = game.score / 200; + if (game.level <0) { + game.level = 0; + } else if (game.level > 9) { + game.level = 9; + } + gameSpeed = (gameInitSpeed-game.level); + } + game.erasingNeeded = false; +} + +void enableErasing(Game game) { + game.erasingNeeded = true; +} + +Block randomBlock() { + int blockType = int(random(0, BlocksCount)); + int blockDirection = int(random(0, DirectionsCount)); + Block block = new Block(blockType, 0, 0, blockDirection); + block.parts = getBlockParts(block); + return block; +} + +void generateRandomBlock(Game game) { + int blockType = int(random(0, BlocksCount)); + int blockDirection = int(random(0, DirectionsCount)); + //int xPos = int(random(0, game.wellWidth)); + int xPos = game.wellWidth/2-1; + //game.fallingBlock = createBlock(blockType, blockDirection, xPos, -1, game.wellWidth); + if (game.nextBlock == null) { + game.fallingBlock = createBlock(blockType, blockDirection, xPos, -1, game.wellWidth); + game.nextBlock = randomBlock(); + } else { + game.fallingBlock = game.nextBlock; + game.fallingBlock.xPos = game.wellWidth/2-1; + arrangeNewBlock(game.fallingBlock, game.wellWidth); + game.nextBlock = randomBlock(); + } +} + +boolean isBlockMovingPossible(Game game, int moveDirection) { + Block block = game.fallingBlock; + if (block == null) + return false; + + boolean possible = true; + for (int i = 0; i < BlockPartsCount; i++) { + + int desiredXPos = block.parts[i].xPos + moveDirection; + int desiredYPos = block.parts[i].yPos; + + possible = possible + && (moveDirection == MoveLeft ? desiredXPos >= 0 : desiredXPos < game.wellWidth); + + if ((desiredYPos >= 0) && (desiredYPos < game.wellHeight)) + possible = possible && !(game.blocks[desiredXPos][desiredYPos]); + } + return possible; +} + +void moveBlock(Game game, int moveDirection) { + if (isBlockMovingPossible(game, moveDirection)) + moveBlockHorizontal(game.fallingBlock, moveDirection); +} + +void makeBlockFall(Game game) { + if (isBlockStuck(game)) { + fixateBlock(game); + enableErasing(game); + generateRandomBlock(game); + } else { + makeBlockFall(game.fallingBlock); + } +} + +void rotateBlock(Game game) { + Block block = game.fallingBlock; + Block rotated = createBlock(block.type, rotateDirection(block.direction), block.xPos, block.yPos, game.wellWidth); + game.fallingBlock = rotated; +} + +Game updateGameState(Game game) { + Game currentGame = game; + if (currentGame.erasingNeeded) { + eraseFilledLines(currentGame); + } else if (currentGame.fallingBlock != null) { + makeBlockFall(currentGame); + } + return currentGame; +} + +boolean isGameOver(Game game) { + for (int i = 0; i < game.wellWidth; i++) + if (game.blocks[i][0]) + return true; + return false; +} \ No newline at end of file diff --git a/Processing/Apps/App_05_1_1_Tetris/TetrisRender.pde b/Processing/Apps/App_05_1_1_Tetris/TetrisRender.pde new file mode 100644 index 0000000..0e8f226 --- /dev/null +++ b/Processing/Apps/App_05_1_1_Tetris/TetrisRender.pde @@ -0,0 +1,56 @@ + + +void drawWellGrid(int w, int h) +{ + for (int x = 0; x < w; x++) { + for (int y = 0; y < h; y++) { + stroke(0xFFBBBB00); + fill(0xFF00FF00); + rect(x*BlockScale, y*BlockScale, BlockScale, BlockScale); + } + } +} + +void drawBlocks(int w, int h, boolean[][] blocks) { + for (int x = 0; x < w; x++) { + for (int y = 0; y < h; y++) { + if (blocks[x][y]) { + //fill(0xFF000000 | (int)random(0xFFFFFF)); // For fun. + fill(0xFF0000FF); + rect(x*BlockScale, y*BlockScale, BlockScale, BlockScale); + } + } + } +} + +void drawFallingBlock(Block block) +{ + if (block == null) + return; + + BlockPart[] parts = block.parts; + + stroke(0x00BB0000); + fill(0xFFFF0000); + + for (int i = 0; i < BlockPartsCount; i++) + rect(parts[i].xPos*BlockScale, parts[i].yPos*BlockScale, BlockScale, BlockScale); +} + +void drawNextBlock(Block block,int x,int y) { + if (block == null) + return; + + BlockPart[] parts = block.parts; + stroke(255,0,0); + fill(255,255,0); + for (int i = 0; i < BlockPartsCount; i++) + rect(parts[i].xPos*BlockScale+x, parts[i].yPos*BlockScale+y, BlockScale, BlockScale); +} + +void drawGameState(Game game) +{ + drawWellGrid(game.wellWidth, game.wellHeight); + drawBlocks(game.wellWidth, game.wellHeight, game.blocks); + drawFallingBlock(game.fallingBlock); +} \ No newline at end of file diff --git a/Processing/Sketchs/Sketch_01_1_1_Blink/Sketch_01_1_1_Blink.pde b/Processing/Sketchs/Sketch_01_1_1_Blink/Sketch_01_1_1_Blink.pde new file mode 100644 index 0000000..0635d0a --- /dev/null +++ b/Processing/Sketchs/Sketch_01_1_1_Blink/Sketch_01_1_1_Blink.pde @@ -0,0 +1,27 @@ +/***************************************************** + * Filename : Sketch_01_1_1_Blink + * Description : Make an led blinking. + * auther : www.freenove.com + * modification: 2016/08/14 + *****************************************************/ +import processing.io.*; + +int ledPin = 17; //define ledPin +boolean ledState = false; //define ledState + +void setup() { + size(100, 100); + frameRate(1); //set frame rate + GPIO.pinMode(ledPin, GPIO.OUTPUT); //set the ledPin to output mode +} + +void draw() { + ledState = !ledState; + if (ledState) { + GPIO.digitalWrite(ledPin, GPIO.HIGH); //led on + background(255, 0, 0); //set the fill color of led on + } else { + GPIO.digitalWrite(ledPin, GPIO.LOW); //led off + background(102); //set the fill color of led off + } +} \ No newline at end of file diff --git a/Processing/Sketchs/Sketch_01_2_1_MouseLED/Sketch_01_2_1_MouseLED.pde b/Processing/Sketchs/Sketch_01_2_1_MouseLED/Sketch_01_2_1_MouseLED.pde new file mode 100644 index 0000000..e02b8cc --- /dev/null +++ b/Processing/Sketchs/Sketch_01_2_1_MouseLED/Sketch_01_2_1_MouseLED.pde @@ -0,0 +1,29 @@ +/***************************************************** + * Filename : Sketch_01_2_1_MouseLED + * Description : Use the mouse to control the LED ON OFF + * auther : www.freenove.com + * modification: 2016/08/14 + *****************************************************/ +import processing.io.*; + +int ledPin = 17; +boolean ledState = false; +void setup() { + size(100, 100); + GPIO.pinMode(ledPin, GPIO.OUTPUT); + background(102); +} + +void draw() { + if (ledState) { + GPIO.digitalWrite(ledPin, GPIO.HIGH); + background(255,0,0); + } else { + GPIO.digitalWrite(ledPin, GPIO.LOW); + background(102); + } +} + +void mouseClicked() { //if the mouse Clicked + ledState = !ledState; //Change the led State +} \ No newline at end of file diff --git a/Processing/Sketchs/Sketch_02_1_1_FollowLight/Sketch_02_1_1_FollowLight.pde b/Processing/Sketchs/Sketch_02_1_1_FollowLight/Sketch_02_1_1_FollowLight.pde new file mode 100644 index 0000000..60683c9 --- /dev/null +++ b/Processing/Sketchs/Sketch_02_1_1_FollowLight/Sketch_02_1_1_FollowLight.pde @@ -0,0 +1,35 @@ +/***************************************************** + * Filename : Sketch_02_1_1_FollowLight + * Description : Use the mouse to control the LEDGraph Bar + * auther : www.freenove.com + * modification: 2016/08/15 + *****************************************************/ +import processing.io.*; + +int leds[]={17, 18, 27, 22, 23, 24, 25, 2, 3, 8}; //define ledPins + +void setup() { + size(640, 360); //display window size + for (int i=0; i<10; i++) { //set led Pins to output mode + GPIO.pinMode(leds[i], GPIO.OUTPUT); + } + background(102); + textAlign(CENTER); //set the text centered + textSize(40); //set text size + text("Follow Light", width / 2, 40); //title + textSize(16); + text("www.freenove.com", width / 2, height - 20); //site +} + +void draw() { + for (int i=0; i<10; i++) { //draw 10 rectanglar box + if (mouseX>(25+60*i)) { //if the mouse cursor on the right of rectanglar box + fill(255, 0, 0); //fill the rectanglar box in red color + GPIO.digitalWrite(leds[i], GPIO.LOW); //turn on the corresponding led + } else { + fill(255, 255, 255); //else fill the rectanglar box in white color and turn off the led + GPIO.digitalWrite(leds[i], GPIO.HIGH); + } + rect(25+60*i, 90, 50, 180); //draw a rectanglar box + } +} \ No newline at end of file diff --git a/Processing/Sketchs/Sketch_03_1_1_BreadthingLED/SOFTPWM.pde b/Processing/Sketchs/Sketch_03_1_1_BreadthingLED/SOFTPWM.pde new file mode 100644 index 0000000..46b259d --- /dev/null +++ b/Processing/Sketchs/Sketch_03_1_1_BreadthingLED/SOFTPWM.pde @@ -0,0 +1,59 @@ +import processing.io.*; + +class SOFTPWM { + public int pin=-1; + public long range = -1; + private Thread t = new Thread(new myThread()); + //private Thread t = new Thread(); + public long marks = 0; //high level time of period + public long space = 0; //low level time of period + public SOFTPWM(int iPin, int dc, int pwmRange) { + pin = iPin; + range = pwmRange*100000; //unit : 0.1ms + marks = dc*100000; + GPIO.pinMode(pin, GPIO.OUTPUT); + t.start(); + } + public void softPwmWrite(int value) { + value *= 100000; + constrain(value, 0, range); + marks = value; + } + public void softPwmStop() { + t.stop(); + GPIO.digitalWrite(pin, GPIO.LOW); + } + private class myThread implements Runnable { + public void run() { + while (true) { + space = range - marks; + if (marks !=0 ) { + GPIO.digitalWrite(pin, GPIO.HIGH); + delayMicroSeconds(marks); + } + if (space !=0 ) { + GPIO.digitalWrite(pin, GPIO.LOW); + delayMicroSeconds(space); + } + //println("mark : "+marks+" space : "+space); + } + } + } +} + +class SEC { + public long msec; + public int nsec; +} +void delayMicroSeconds(long howlong) { + SEC s = new SEC(); + s.msec = howlong / 1000000; + s.nsec = (int)howlong % 1000000; + try { + Thread.sleep(s.msec, s.nsec); + } + catch(Exception e) { + println(e); + println("msec: "+s.msec+" nsec: "+s.nsec); + } +} \ No newline at end of file diff --git a/Processing/Sketchs/Sketch_03_1_1_BreadthingLED/Sketch_03_1_1_BreadthingLED.pde b/Processing/Sketchs/Sketch_03_1_1_BreadthingLED/Sketch_03_1_1_BreadthingLED.pde new file mode 100644 index 0000000..f5cf45e --- /dev/null +++ b/Processing/Sketchs/Sketch_03_1_1_BreadthingLED/Sketch_03_1_1_BreadthingLED.pde @@ -0,0 +1,73 @@ +/***************************************************** + * Filename : Sketch_03_1_1_BreathingLED + * Description : Using PWM control LED brightness + * auther : www.freenove.com + * modification: 2016/08/18 + *****************************************************/ +import processing.io.*; + +int ledPin = 17; //led Pin +int borderSize = 40; // +float t = 0.0; //progress percent +float tStep = 0.004; // speed +SOFTPWM p = new SOFTPWM(ledPin, 10, 100); //Create a PWM pin,initialize the duty cycle and period +void setup() { + size(640, 360); //display window size + strokeWeight(4); //stroke Weight +} + +void draw() { + // Show static value when mouse is pressed, animate otherwise + if (mousePressed) { + int a = constrain(mouseX, borderSize, width - borderSize); + t = map(a, borderSize, width - borderSize, 0.0, 1.0); + } else { + t += tStep; + if (t > 1.0) t = 0.0; + } + p.softPwmWrite((int)(t*100)); //wirte the duty cycle according to t + background(255); //A white background + titleAndSiteInfo(); //title and Site infomation + + fill(255, 255-t*255, 255-t*255); //cycle + ellipse(width/2, height/2, 100, 100); + + pushMatrix(); + translate(borderSize, height - 45); + int barLength = width - 2*borderSize; + + barBgStyle(); //progressbar bg + line(0, 0, barLength, 0); + line(barLength, -5, barLength, 5); + + barStyle(); //progressbar + line(0, -5, 0, 5); + line(0, 0, t*barLength, 0); + + barLabelStyle(); //progressbar label + text("progress : "+nf(t*100,2,2),barLength/2,-25); + popMatrix(); +} + +void titleAndSiteInfo() { + fill(0); + textAlign(CENTER); //set the text centered + textSize(40); //set text size + text("Breathing Light", width / 2, 40); //title + textSize(16); + text("www.freenove.com", width / 2, height - 20); //site +} +void barBgStyle() { + stroke(220); + noFill(); +} + +void barStyle() { + stroke(50); + noFill(); +} + +void barLabelStyle() { + noStroke(); + fill(120); +} \ No newline at end of file diff --git a/Processing/Sketchs/Sketch_04_1_1_ColorfulLED/ProgressBar.pde b/Processing/Sketchs/Sketch_04_1_1_ColorfulLED/ProgressBar.pde new file mode 100644 index 0000000..d9bbfc4 --- /dev/null +++ b/Processing/Sketchs/Sketch_04_1_1_ColorfulLED/ProgressBar.pde @@ -0,0 +1,71 @@ + + +class ProgressBar { + + int x, y; + int barLength; + float progress; + String title; + public ProgressBar(int ix, int iy, int barlen) { + x = ix; + y = iy; + barLength = barlen; + progress = 0; + title = "Progress"; + } + public void setTitle(String str){ + title = str; + } + public void setProgress(float pgress) { + constrain(pgress, 0, 1.0); + progress = pgress; + } + public void create() { + pushMatrix(); + translate(x, y); + textAlign(CENTER); + textSize(16); + barBgStyle(); //progressbar bg + line(0, 0, barLength, 0); + line(barLength, -5, barLength, 5); + + barStyle(); //progressbar + line(0, -5, 0, 5); + line(0, 0, progress*barLength, 0); + + barLabelStyle(); //progressbar label + text(title+" : "+nf(progress*100, 2, 2)+"%", barLength/2, -5); + popMatrix(); + } + public void create(float pgress) { + setProgress(pgress); + pushMatrix(); + translate(x, y); + + barBgStyle(); //progressbar bg + line(0, 0, barLength, 0); + line(barLength, -5, barLength, 5); + + barStyle(); //progressbar + line(0, -5, 0, 5); + line(0, 0, progress*barLength, 0); + + barLabelStyle(); //progressbar label + text(title+" : "+nf(progress*100, 2, 2)+"%", barLength/2, -5); + popMatrix(); + } + void barBgStyle() { + stroke(220); + noFill(); + } + + void barStyle() { + stroke(50); + noFill(); + } + + void barLabelStyle() { + noStroke(); + fill(120); + } +} \ No newline at end of file diff --git a/Processing/Sketchs/Sketch_04_1_1_ColorfulLED/SOFTPWM.pde b/Processing/Sketchs/Sketch_04_1_1_ColorfulLED/SOFTPWM.pde new file mode 100644 index 0000000..46b259d --- /dev/null +++ b/Processing/Sketchs/Sketch_04_1_1_ColorfulLED/SOFTPWM.pde @@ -0,0 +1,59 @@ +import processing.io.*; + +class SOFTPWM { + public int pin=-1; + public long range = -1; + private Thread t = new Thread(new myThread()); + //private Thread t = new Thread(); + public long marks = 0; //high level time of period + public long space = 0; //low level time of period + public SOFTPWM(int iPin, int dc, int pwmRange) { + pin = iPin; + range = pwmRange*100000; //unit : 0.1ms + marks = dc*100000; + GPIO.pinMode(pin, GPIO.OUTPUT); + t.start(); + } + public void softPwmWrite(int value) { + value *= 100000; + constrain(value, 0, range); + marks = value; + } + public void softPwmStop() { + t.stop(); + GPIO.digitalWrite(pin, GPIO.LOW); + } + private class myThread implements Runnable { + public void run() { + while (true) { + space = range - marks; + if (marks !=0 ) { + GPIO.digitalWrite(pin, GPIO.HIGH); + delayMicroSeconds(marks); + } + if (space !=0 ) { + GPIO.digitalWrite(pin, GPIO.LOW); + delayMicroSeconds(space); + } + //println("mark : "+marks+" space : "+space); + } + } + } +} + +class SEC { + public long msec; + public int nsec; +} +void delayMicroSeconds(long howlong) { + SEC s = new SEC(); + s.msec = howlong / 1000000; + s.nsec = (int)howlong % 1000000; + try { + Thread.sleep(s.msec, s.nsec); + } + catch(Exception e) { + println(e); + println("msec: "+s.msec+" nsec: "+s.nsec); + } +} \ No newline at end of file diff --git a/Processing/Sketchs/Sketch_04_1_1_ColorfulLED/Sketch_04_1_1_ColorfulLED.pde b/Processing/Sketchs/Sketch_04_1_1_ColorfulLED/Sketch_04_1_1_ColorfulLED.pde new file mode 100644 index 0000000..c87479e --- /dev/null +++ b/Processing/Sketchs/Sketch_04_1_1_ColorfulLED/Sketch_04_1_1_ColorfulLED.pde @@ -0,0 +1,81 @@ +/***************************************************** + * Filename : Sketch_04_1_1_ColorfulLED + * Description : Using slider controlRGBLED + * auther : www.freenove.com + * modification: 2016/08/20 + *****************************************************/ +import processing.io.*; + +int bluePin = 17; //blue Pin +int greenPin = 27; //green Pin +int redPin = 22; //red Pin +int borderSize = 40; //picture border size +//Create a PWM pin,initialize the duty cycle and period +SOFTPWM pRed = new SOFTPWM(redPin, 100, 100); +SOFTPWM pGreen = new SOFTPWM(greenPin, 100, 100); +SOFTPWM pBlue = new SOFTPWM(bluePin, 100, 100); +//instantiate three ProgressBar Object +ProgressBar rBar, gBar, bBar; +boolean rMouse = false, gMouse = false, bMouse = false; +void setup() { + size(640, 360); //display window size + strokeWeight(4); //stroke Weight + //define the ProgressBar length + int barLength = width - 2*borderSize; + //Create ProgressBar Object + rBar = new ProgressBar(borderSize, height - 85, barLength); + gBar = new ProgressBar(borderSize, height - 65, barLength); + bBar = new ProgressBar(borderSize, height - 45, barLength); + //Set ProgressBar's title + rBar.setTitle("Red");gBar.setTitle("Green");bBar.setTitle("Blue"); +} + +void draw() { + background(200); //A white background + titleAndSiteInfo(); //title and Site infomation + + fill(rBar.progress*255, gBar.progress*255, bBar.progress*255); //cycle color + ellipse(width/2, height/2, 100, 100); //show cycle + + rBar.create(); //Show progressBar + gBar.create(); + bBar.create(); +} + +void mousePressed() { + if ( (mouseY< rBar.y+5) && (mouseY>rBar.y-5) ) { + rMouse = true; + } else if ( (mouseY< gBar.y+5) && (mouseY>gBar.y-5) ) { + gMouse = true; + } else if ( (mouseY< bBar.y+5) && (mouseY>bBar.y-5) ) { + bMouse = true; + } +} +void mouseReleased() { + rMouse = false; + bMouse = false; + gMouse = false; +} +void mouseDragged() { + int a = constrain(mouseX, borderSize, width - borderSize); + float t = map(a, borderSize, width - borderSize, 0.0, 1.0); + if (rMouse) { + pRed.softPwmWrite((int)(100-t*100)); //wirte the duty cycle according to t + rBar.setProgress(t); + } else if (gMouse) { + pGreen.softPwmWrite((int)(100-t*100)); //wirte the duty cycle according to t + gBar.setProgress(t); + } else if (bMouse) { + pBlue.softPwmWrite((int)(100-t*100)); //wirte the duty cycle according to t + bBar.setProgress(t); + } +} + +void titleAndSiteInfo() { + fill(0); + textAlign(CENTER); //set the text centered + textSize(40); //set text size + text("Colorful LED", width / 2, 40); //title + textSize(16); + text("www.freenove.com", width / 2, height - 20); //site +} \ No newline at end of file diff --git a/Processing/Sketchs/Sketch_05_1_1_ActiveBuzzer/Sketch_05_1_1_ActiveBuzzer.pde b/Processing/Sketchs/Sketch_05_1_1_ActiveBuzzer/Sketch_05_1_1_ActiveBuzzer.pde new file mode 100644 index 0000000..ecb7572 --- /dev/null +++ b/Processing/Sketchs/Sketch_05_1_1_ActiveBuzzer/Sketch_05_1_1_ActiveBuzzer.pde @@ -0,0 +1,52 @@ +/***************************************************** + * Filename : Sketch_05_1_1_Activebuzzer + * Description : Use the mouse to control the Active buzzer ON or OFF + * auther : www.freenove.com + * modification: 2016/08/14 + *****************************************************/ +import processing.io.*; + +int buzzerPin = 17; +boolean buzzerState = false; +void setup() { + size(640, 360); + GPIO.pinMode(buzzerPin, GPIO.OUTPUT); +} + +void draw() { + background(255); + titleAndSiteInfo(); //title and site infomation + drawBuzzer(); //buzzer img + if (buzzerState) { + GPIO.digitalWrite(buzzerPin, GPIO.HIGH); + drawArc(); //Sounds waves img + } else { + GPIO.digitalWrite(buzzerPin, GPIO.LOW); + } +} + +void mouseClicked() { //if the mouse Clicked + buzzerState = !buzzerState; //Change the buzzer State +} +void drawBuzzer() { + strokeWeight(1); + fill(0); + ellipse(width/2, height/2, 50, 50); + fill(255); + ellipse(width/2, height/2, 10, 10); +} +void drawArc() { + noFill(); + strokeWeight(8); + for (int i=0; i<3; i++) { + arc(width/2, height/2, 100*(1+i), 100*(1+i), -PI/4, PI/4, OPEN); + } +} +void titleAndSiteInfo() { + fill(0); + textAlign(CENTER); //set the text centered + textSize(40); //set text size + text("Active Buzzer", width / 2, 40); //title + textSize(16); + text("www.freenove.com", width / 2, height - 20); //site +} \ No newline at end of file diff --git a/Processing/Sketchs/Sketch_06_1_1_PCF8591/PCF8591.pde b/Processing/Sketchs/Sketch_06_1_1_PCF8591/PCF8591.pde new file mode 100644 index 0000000..267a48a --- /dev/null +++ b/Processing/Sketchs/Sketch_06_1_1_PCF8591/PCF8591.pde @@ -0,0 +1,47 @@ +/***************************************************** + * Filename : PCF8591 + * Description : class PCF8591,DAC and ADC + * auther : www.freenove.com + * modification: 2016/08/20 + *****************************************************/ + +class PCF8591 { + private int address; + private I2C i2c; + //constructor,Parameters for the PCF8591 I2C address + public PCF8591(int addr) { + address = addr; + i2c = new I2C(I2C.list()[0]); + } + //Read the ADC value of one channel + public int analogRead(int chn) { + int result = 0; + i2c.beginTransmission(address); + constrain(chn, 0, 3); + i2c.write(0x40 | chn); + try { + byte[] in = i2c.read(1); + result = in[0]&0xff; + } + catch(Exception e) { + println(e); + } + i2c.endTransmission(); + return result; + } + //Read the ADC value of all channels + public byte[] analogRead() { + i2c.beginTransmission(address); + i2c.write(0x44); + i2c.endTransmission(); + byte[] in = i2c.read(4); + return in; + } + //Write the DACvalue + public void analogWrite(int data) { + i2c.beginTransmission(address); + i2c.write(0x40); + i2c.write(data); + i2c.endTransmission(); + } +} \ No newline at end of file diff --git a/Processing/Sketchs/Sketch_06_1_1_PCF8591/Sketch_06_1_1_PCF8591.pde b/Processing/Sketchs/Sketch_06_1_1_PCF8591/Sketch_06_1_1_PCF8591.pde new file mode 100644 index 0000000..466f055 --- /dev/null +++ b/Processing/Sketchs/Sketch_06_1_1_PCF8591/Sketch_06_1_1_PCF8591.pde @@ -0,0 +1,36 @@ +/***************************************************** + * Filename : Sketch_06_1_1_PCF8591 + * Description : ADC and DAC of PCF8591 + * auther : www.freenove.com + * modification: 2016/08/20 + *****************************************************/ +import processing.io.*; +//Create a object of class PCF8591 +PCF8591 pcf = new PCF8591(0x48); +void setup() { + size(640, 360); +} +void draw() { + int adc = pcf.analogRead(0); //Read the ADC value of channel 0 + float volt = adc*3.3/255.0; //calculate the voltage + pcf.analogWrite(adc); //Write the DAC + background(255); + titleAndSiteInfo(); + + fill(0); + textAlign(CENTER); //set the text centered + textSize(30); + text("ADC: "+nf(adc, 3, 0), width / 2, height/2+50); + textSize(30); + text("DAC: "+nf(adc, 3, 0), width / 2, height/2+100); + textSize(40); //set text size + text("Voltage: "+nf(volt, 0, 2)+"V", width / 2, height/2); // +} +void titleAndSiteInfo() { + fill(0); + textAlign(CENTER); //set the text centered + textSize(40); //set text size + text("ADC & DAC", width / 2, 40); //title + textSize(16); + text("www.freenove.com", width / 2, height - 20); //site +} \ No newline at end of file diff --git a/Processing/Sketchs/Sketch_07_1_1_SoftLight/PCF8591.pde b/Processing/Sketchs/Sketch_07_1_1_SoftLight/PCF8591.pde new file mode 100644 index 0000000..267a48a --- /dev/null +++ b/Processing/Sketchs/Sketch_07_1_1_SoftLight/PCF8591.pde @@ -0,0 +1,47 @@ +/***************************************************** + * Filename : PCF8591 + * Description : class PCF8591,DAC and ADC + * auther : www.freenove.com + * modification: 2016/08/20 + *****************************************************/ + +class PCF8591 { + private int address; + private I2C i2c; + //constructor,Parameters for the PCF8591 I2C address + public PCF8591(int addr) { + address = addr; + i2c = new I2C(I2C.list()[0]); + } + //Read the ADC value of one channel + public int analogRead(int chn) { + int result = 0; + i2c.beginTransmission(address); + constrain(chn, 0, 3); + i2c.write(0x40 | chn); + try { + byte[] in = i2c.read(1); + result = in[0]&0xff; + } + catch(Exception e) { + println(e); + } + i2c.endTransmission(); + return result; + } + //Read the ADC value of all channels + public byte[] analogRead() { + i2c.beginTransmission(address); + i2c.write(0x44); + i2c.endTransmission(); + byte[] in = i2c.read(4); + return in; + } + //Write the DACvalue + public void analogWrite(int data) { + i2c.beginTransmission(address); + i2c.write(0x40); + i2c.write(data); + i2c.endTransmission(); + } +} \ No newline at end of file diff --git a/Processing/Sketchs/Sketch_07_1_1_SoftLight/SOFTPWM.pde b/Processing/Sketchs/Sketch_07_1_1_SoftLight/SOFTPWM.pde new file mode 100644 index 0000000..46b259d --- /dev/null +++ b/Processing/Sketchs/Sketch_07_1_1_SoftLight/SOFTPWM.pde @@ -0,0 +1,59 @@ +import processing.io.*; + +class SOFTPWM { + public int pin=-1; + public long range = -1; + private Thread t = new Thread(new myThread()); + //private Thread t = new Thread(); + public long marks = 0; //high level time of period + public long space = 0; //low level time of period + public SOFTPWM(int iPin, int dc, int pwmRange) { + pin = iPin; + range = pwmRange*100000; //unit : 0.1ms + marks = dc*100000; + GPIO.pinMode(pin, GPIO.OUTPUT); + t.start(); + } + public void softPwmWrite(int value) { + value *= 100000; + constrain(value, 0, range); + marks = value; + } + public void softPwmStop() { + t.stop(); + GPIO.digitalWrite(pin, GPIO.LOW); + } + private class myThread implements Runnable { + public void run() { + while (true) { + space = range - marks; + if (marks !=0 ) { + GPIO.digitalWrite(pin, GPIO.HIGH); + delayMicroSeconds(marks); + } + if (space !=0 ) { + GPIO.digitalWrite(pin, GPIO.LOW); + delayMicroSeconds(space); + } + //println("mark : "+marks+" space : "+space); + } + } + } +} + +class SEC { + public long msec; + public int nsec; +} +void delayMicroSeconds(long howlong) { + SEC s = new SEC(); + s.msec = howlong / 1000000; + s.nsec = (int)howlong % 1000000; + try { + Thread.sleep(s.msec, s.nsec); + } + catch(Exception e) { + println(e); + println("msec: "+s.msec+" nsec: "+s.nsec); + } +} \ No newline at end of file diff --git a/Processing/Sketchs/Sketch_07_1_1_SoftLight/Sketch_07_1_1_SoftLight.pde b/Processing/Sketchs/Sketch_07_1_1_SoftLight/Sketch_07_1_1_SoftLight.pde new file mode 100644 index 0000000..b66fcc5 --- /dev/null +++ b/Processing/Sketchs/Sketch_07_1_1_SoftLight/Sketch_07_1_1_SoftLight.pde @@ -0,0 +1,41 @@ +/***************************************************** + * Filename : Sketch_07_1_1_SoftLight + * Description : control the brightness of led through a potentiometer + * auther : www.freenove.com + * modification: 2016/08/20 + *****************************************************/ +import processing.io.*; + +int ledPin = 17; //led +//Create a object of class PCF8591 +PCF8591 pcf = new PCF8591(0x48); +SOFTPWM p = new SOFTPWM(ledPin, 0, 100); +void setup() { + size(640, 360); +} +void draw() { + int adc = pcf.analogRead(0); //Read the ADC value of channel 0 + float volt = adc*3.3/255.0; //calculate the voltage + float dt = adc/255.0; + p.softPwmWrite((int)(dt*100)); //output the pwm + background(255); + titleAndSiteInfo(); + + fill(255, 255-dt*255, 255-dt*255); //cycle + noStroke(); //no border + ellipse(width/2, height/2, 100, 100); + + fill(0); + textAlign(CENTER); //set the text centered + textSize(30); + text("ADC: "+nf(adc, 3, 0), width / 2, height/2+130); + text("Voltage: "+nf(volt, 0, 2)+"V", width / 2, height/2+100); // +} +void titleAndSiteInfo() { + fill(0); + textAlign(CENTER); //set the text centered + textSize(40); //set text size + text("SoftLight", width / 2, 40); //title + textSize(16); + text("www.freenove.com", width / 2, height - 20); //site +} \ No newline at end of file diff --git a/Processing/Sketchs/Sketch_08_1_1_Thermometer/PCF8591.pde b/Processing/Sketchs/Sketch_08_1_1_Thermometer/PCF8591.pde new file mode 100644 index 0000000..267a48a --- /dev/null +++ b/Processing/Sketchs/Sketch_08_1_1_Thermometer/PCF8591.pde @@ -0,0 +1,47 @@ +/***************************************************** + * Filename : PCF8591 + * Description : class PCF8591,DAC and ADC + * auther : www.freenove.com + * modification: 2016/08/20 + *****************************************************/ + +class PCF8591 { + private int address; + private I2C i2c; + //constructor,Parameters for the PCF8591 I2C address + public PCF8591(int addr) { + address = addr; + i2c = new I2C(I2C.list()[0]); + } + //Read the ADC value of one channel + public int analogRead(int chn) { + int result = 0; + i2c.beginTransmission(address); + constrain(chn, 0, 3); + i2c.write(0x40 | chn); + try { + byte[] in = i2c.read(1); + result = in[0]&0xff; + } + catch(Exception e) { + println(e); + } + i2c.endTransmission(); + return result; + } + //Read the ADC value of all channels + public byte[] analogRead() { + i2c.beginTransmission(address); + i2c.write(0x44); + i2c.endTransmission(); + byte[] in = i2c.read(4); + return in; + } + //Write the DACvalue + public void analogWrite(int data) { + i2c.beginTransmission(address); + i2c.write(0x40); + i2c.write(data); + i2c.endTransmission(); + } +} \ No newline at end of file diff --git a/Processing/Sketchs/Sketch_08_1_1_Thermometer/Sketch_08_1_1_Thermometer.pde b/Processing/Sketchs/Sketch_08_1_1_Thermometer/Sketch_08_1_1_Thermometer.pde new file mode 100644 index 0000000..6b80aba --- /dev/null +++ b/Processing/Sketchs/Sketch_08_1_1_Thermometer/Sketch_08_1_1_Thermometer.pde @@ -0,0 +1,40 @@ +/***************************************************** + * Filename : Sketch_08_1_1_Thermometer + * Description : A DIY Thermometer + * auther : www.freenove.com + * modification: 2016/08/21 + *****************************************************/ +import processing.io.*; +//Create a object of class PCF8591 +PCF8591 pcf = new PCF8591(0x48); +void setup() { + size(640, 360); +} +void draw() { + int adc = pcf.analogRead(0); //Read the ADC value of channel 0 + float volt = adc*3.3/255.0; //calculate the voltage + float tempK,tempC,Rt; // + Rt = 10*volt / (3.3-volt); //calculate the resistance value of thermistor + tempK = 1/(1/(273.15+25) + log(Rt/10)/3950); //calaulate temperature(Kelvin) + tempC = tempK - 273.15; //calaulate temperature(Celsius) + + background(255); + titleAndSiteInfo(); + + fill(0); + textAlign(CENTER); //set the text centered + textSize(30); + text("ADC: "+nf(adc, 0, 0), width / 2, height/2+50); + textSize(30); + text("voltage: "+nf(volt, 0, 2)+"V", width / 2, height/2+100); + textSize(40); //set text size + text("Temperature: "+nf(tempC, 0, 2)+" C", width / 2, height/2); // +} +void titleAndSiteInfo() { + fill(0); + textAlign(CENTER); //set the text centered + textSize(40); //set text size + text("Thermometer", width / 2, 40); //title + textSize(16); + text("www.freenove.com", width / 2, height - 20); //site +} \ No newline at end of file diff --git a/Processing/Sketchs/Sketch_09_1_1_Motor/BUTTON.pde b/Processing/Sketchs/Sketch_09_1_1_Motor/BUTTON.pde new file mode 100644 index 0000000..4332306 --- /dev/null +++ b/Processing/Sketchs/Sketch_09_1_1_Motor/BUTTON.pde @@ -0,0 +1,51 @@ +/***************************************************** + * Filename : BUTTON + * Description : class BUTTON + * auther : www.freenove.com + * modification: 2016/08/22 + *****************************************************/ +class BUTTON { + public int x, y, w, h; + public String txt; + private int bgr, bgg, bgb; + private int tr, tg, tb; + public BUTTON(int ix, int iy, int iw, int ih) { + setPosition(ix, iy); + setSize(iw, ih); + setText("BTN"); + setBgColor(0, 0, 0); + setTextColor(255,255,255); + } + public void create() { + pushMatrix(); + translate(x,y); + fill(bgr, bgg, bgb); + rect(0, 0, w, h); + fill(tr, tg, tb); + textSize(min(w,h)/2); + textAlign(CENTER, CENTER); + text(txt, w/2, h/2); + popMatrix(); + } + public void setBgColor(int ir, int ig, int ib) { + bgr = ir; + bgg = ig; + bgb = ib; + } + public void setText(String str) { + txt = str; + } + public void setTextColor(int ir, int ig, int ib) { + tr = ir; + tg = ig; + tb = ib; + } + public void setSize(int iw, int ih) { + w = iw; + h = ih; + } + public void setPosition(int ix, int iy) { + x= ix; + y = iy; + } +} \ No newline at end of file diff --git a/Processing/Sketchs/Sketch_09_1_1_Motor/MOTOR.pde b/Processing/Sketchs/Sketch_09_1_1_Motor/MOTOR.pde new file mode 100644 index 0000000..f418439 --- /dev/null +++ b/Processing/Sketchs/Sketch_09_1_1_Motor/MOTOR.pde @@ -0,0 +1,46 @@ +/***************************************************** + * Filename : MOTOR + * Description : class MOTOR + * auther : www.freenove.com + * modification: 2016/08/22 + *****************************************************/ + +import processing.io.*; + +class MOTOR { + int mPin1, mPin2, enPin; + SOFTPWM p; + public int dir; + final public int CW = 1, CCW = 2, STOP = 3; + public MOTOR(int pin1, int pin2, int enablePin) { + mPin1 = pin1; + mPin2 = pin2; + enPin = enablePin; + GPIO.pinMode(mPin1, GPIO.OUTPUT); + GPIO.pinMode(mPin2, GPIO.OUTPUT); + p = new SOFTPWM(enPin, 0, 100); + dir = 0; + } + public void start(int dir, int speed) { + switch(dir) { + case CW: + GPIO.digitalWrite(mPin1, GPIO.HIGH); + GPIO.digitalWrite(mPin2, GPIO.LOW); + break; + case CCW: + GPIO.digitalWrite(mPin1, GPIO.LOW); + GPIO.digitalWrite(mPin2, GPIO.HIGH); + break; + case STOP: + GPIO.digitalWrite(mPin1, GPIO.LOW); + GPIO.digitalWrite(mPin2, GPIO.LOW); + break; + default: + GPIO.digitalWrite(mPin1, GPIO.LOW); + GPIO.digitalWrite(mPin2, GPIO.LOW); + break; + } + constrain(speed, 0, 100); + p.softPwmWrite(speed); + } +} \ No newline at end of file diff --git a/Processing/Sketchs/Sketch_09_1_1_Motor/ProgressBar.pde b/Processing/Sketchs/Sketch_09_1_1_Motor/ProgressBar.pde new file mode 100644 index 0000000..f9aacf4 --- /dev/null +++ b/Processing/Sketchs/Sketch_09_1_1_Motor/ProgressBar.pde @@ -0,0 +1,76 @@ +/***************************************************** + * Filename : ProgressBar + * Description : class ProgressBar + * auther : www.freenove.com + * modification: 2016/08/22 + *****************************************************/ + +class ProgressBar { + + int x, y; + int barLength; + float progress; + String title; + public ProgressBar(int ix, int iy, int barlen) { + x = ix; + y = iy; + barLength = barlen; + progress = 0; + title = "Progress"; + } + public void setTitle(String str){ + title = str; + } + public void setProgress(float pgress) { + constrain(pgress, 0, 1.0); + progress = pgress; + } + public void create() { + pushMatrix(); + translate(x, y); + textAlign(CENTER); + textSize(16); + barBgStyle(); //progressbar bg + line(0, 0, barLength, 0); + line(barLength, -5, barLength, 5); + + barStyle(); //progressbar + line(0, -5, 0, 5); + line(0, 0, progress*barLength, 0); + + barLabelStyle(); //progressbar label + text(title+" : "+nf(progress*100, 2, 2)+"%", barLength/2, -5); + popMatrix(); + } + public void create(float pgress) { + setProgress(pgress); + pushMatrix(); + translate(x, y); + + barBgStyle(); //progressbar bg + line(0, 0, barLength, 0); + line(barLength, -5, barLength, 5); + + barStyle(); //progressbar + line(0, -5, 0, 5); + line(0, 0, progress*barLength, 0); + + barLabelStyle(); //progressbar label + text(title+" : "+nf(progress*100, 2, 2)+"%", barLength/2, -5); + popMatrix(); + } + void barBgStyle() { + stroke(220); + noFill(); + } + + void barStyle() { + stroke(50); + noFill(); + } + + void barLabelStyle() { + noStroke(); + fill(120); + } +} \ No newline at end of file diff --git a/Processing/Sketchs/Sketch_09_1_1_Motor/SOFTPWM.pde b/Processing/Sketchs/Sketch_09_1_1_Motor/SOFTPWM.pde new file mode 100644 index 0000000..ac2300f --- /dev/null +++ b/Processing/Sketchs/Sketch_09_1_1_Motor/SOFTPWM.pde @@ -0,0 +1,65 @@ +/***************************************************** + * Filename : SOFTPWM + * Description : class SOFTPWM + * auther : www.freenove.com + * modification: 2016/08/22 + *****************************************************/ +import processing.io.*; + +class SOFTPWM { + public int pin=-1; + public long range = -1; + private Thread t = new Thread(new myThread()); + //private Thread t = new Thread(); + public long marks = 0; //high level time of period + public long space = 0; //low level time of period + public SOFTPWM(int iPin, int dc, int pwmRange) { + pin = iPin; + range = pwmRange*100000; //unit : 0.1ms + marks = dc*100000; + GPIO.pinMode(pin, GPIO.OUTPUT); + t.start(); + } + public void softPwmWrite(int value) { + value *= 100000; + constrain(value, 0, range); + marks = value; + } + public void softPwmStop() { + t.stop(); + GPIO.digitalWrite(pin, GPIO.LOW); + } + private class myThread implements Runnable { + public void run() { + while (true) { + space = range - marks; + if (marks !=0 ) { + GPIO.digitalWrite(pin, GPIO.HIGH); + delayMicroSeconds(marks); + } + if (space !=0 ) { + GPIO.digitalWrite(pin, GPIO.LOW); + delayMicroSeconds(space); + } + //println("mark : "+marks+" space : "+space); + } + } + } +} + +class SEC { + public long msec; + public int nsec; +} +void delayMicroSeconds(long howlong) { + SEC s = new SEC(); + s.msec = howlong / 1000000; + s.nsec = (int)howlong % 1000000; + try { + Thread.sleep(s.msec, s.nsec); + } + catch(Exception e) { + println(e); + println("msec: "+s.msec+" nsec: "+s.nsec); + } +} \ No newline at end of file diff --git a/Processing/Sketchs/Sketch_09_1_1_Motor/Sketch_09_1_1_Motor.pde b/Processing/Sketchs/Sketch_09_1_1_Motor/Sketch_09_1_1_Motor.pde new file mode 100644 index 0000000..e044518 --- /dev/null +++ b/Processing/Sketchs/Sketch_09_1_1_Motor/Sketch_09_1_1_Motor.pde @@ -0,0 +1,96 @@ +/***************************************************** + * Filename : Sketch_09_1_1_Motor + * Description : Control speed and direction of the motor + * auther : www.freenove.com + * modification: 2016/08/22 + *****************************************************/ +import processing.io.*; + +int motorPin1 = 17; //connect to the L293D +int motorPin2 = 27; +int enablePin = 22; +final int borderSize = 45; //border size +//MOTOR Object +MOTOR motor = new MOTOR(motorPin1, motorPin2, enablePin); +ProgressBar mBar; //ProgressBar Object +boolean mMouse = false; //determined whether a mouse click the ProgressBar +BUTTON btn; //BUTTON Object, For controlling the direction of motor +int motorDir = motor.CW; //motor direction +float rotaSpeed = 0, rotaPosition = 0; //motor speed +void setup() { + size(640, 360); + mBar = new ProgressBar(borderSize, height-borderSize, width-borderSize*2); + mBar.setTitle("Duty Cycle"); //set the ProgressBar's title + btn = new BUTTON(45, height - 90, 50, 30); //define the button + btn.setBgColor(0, 255, 0); //set button color + btn.setText("CW"); //set button text +} + +void draw() { + background(255); + titleAndSiteInfo(); //title and site information + strokeWeight(4); //border weight + mBar.create(); //create the ProgressBar + motor.start(motorDir, (int)(mBar.progress*100)); //control the motor starts to rotate + btn.create(); //create the button + rotaSpeed = mBar.progress * 0.02 * PI; //virtual fan's rotating speed + if (motorDir == motor.CW) { + rotaPosition += rotaSpeed; + if (rotaPosition >= 2*PI) { + rotaPosition = 0; + } + } else { + rotaPosition -= rotaSpeed; + if (rotaPosition <= -2*PI) { + rotaPosition = 0; + } + } + drawFan(rotaPosition); //show the virtual fan in Display window +} +//Draw a clover fan according to the stating angle +void drawFan(float angle) { + constrain(angle, 0, 2*PI); + fill(0); + for (int i=0; i<3; i++) { + arc(width/2, height/2, 200, 200, 2*i*PI/3+angle, (2*i+0.3)*PI/3+angle, PIE); + } + fill(0); + ellipse(width/2, height/2, 30, 30); + fill(128); + ellipse(width/2, height/2, 15, 15); +} + +void mousePressed() { + if ( (mouseY< mBar.y+5) && (mouseY>mBar.y-5) ) { + mMouse = true; //the mouse click the progressBar + } else if ((mouseY< btn.y+btn.h) && (mouseY>btn.y) + && (mouseX< btn.x+btn.w) && (mouseX>btn.x)) { // the mouse click the button + if (motorDir == motor.CW) { //change the direction of rotation of motor + motorDir = motor.CCW; + btn.setBgColor(255, 0, 0); + btn.setText("CCW"); + } else if (motorDir == motor.CCW) { + motorDir = motor.CW; + btn.setBgColor(0, 255, 0); + btn.setText("CW"); + } + } +} +void mouseReleased() { + mMouse = false; +} +void mouseDragged() { + int a = constrain(mouseX, borderSize, width - borderSize); + float t = map(a, borderSize, width - borderSize, 0.0, 1.0); + if (mMouse) { + mBar.setProgress(t); + } +} +void titleAndSiteInfo() { + fill(0); + textAlign(CENTER); //set the text centered + textSize(40); //set text size + text("Motor", width / 2, 40); //title + textSize(16); + text("www.freenove.com", width / 2, height - 20); //site +} \ No newline at end of file diff --git a/Processing/Sketchs/Sketch_10_1_1_LightWater/IC74HC595.pde b/Processing/Sketchs/Sketch_10_1_1_LightWater/IC74HC595.pde new file mode 100644 index 0000000..8277f59 --- /dev/null +++ b/Processing/Sketchs/Sketch_10_1_1_LightWater/IC74HC595.pde @@ -0,0 +1,38 @@ +/***************************************************** + * Filename : IC74HC595 + * Description : class IC74HC595 + * auther : www.freenove.com + * modification: 2016/08/22 + *****************************************************/ +import processing.io.*; + +class IC74HC595 { + final int LSBFIRST = 1; + final int MSBFIRST = 2; + int dataPin, latchPin, clockPin; + public IC74HC595(int dPin, int lPin, int cPin) { + dataPin = dPin; + latchPin = lPin; + clockPin = cPin; + GPIO.pinMode(dataPin, GPIO.OUTPUT); + GPIO.pinMode(latchPin, GPIO.OUTPUT); + GPIO.pinMode(clockPin, GPIO.OUTPUT); + } + public void write(int order,int value) { + constrain(order,1,2); + GPIO.digitalWrite(latchPin,GPIO.LOW); + shiftOut(order,value); + GPIO.digitalWrite(latchPin,GPIO.HIGH); + } + private void shiftOut(int order, int val) { + for (int i = 0; i<8; i++) { + GPIO.digitalWrite(clockPin, GPIO.LOW); + if (order == LSBFIRST) { + GPIO.digitalWrite(dataPin, ((0x01&(val>>i))==0x01) ? GPIO.HIGH : GPIO.LOW); + } else if (order == MSBFIRST) { + GPIO.digitalWrite(dataPin, ((0x80&(val< 50/(0.05+mBar.progress)) { + lastMoveTime = millis(); + leds<<=1; + if (leds == 0x100) + leds = 0x01; + } + ic.write(ic.LSBFIRST, leds); //write 74HC595 + + stroke(0); + strokeWeight(1); + for (int i=0; i<10; i++) { //draw 10 rectanglar box + if (leds == (1<mBar.y-5) ) { + mMouse = true; //the mouse click the progressBar + } +} +void mouseReleased() { + mMouse = false; +} +void mouseDragged() { + int a = constrain(mouseX, borderSize, width - borderSize); + float t = map(a, borderSize, width - borderSize, 0.0, 1.0); + if (mMouse) { + mBar.setProgress(t); + } +} +void titleAndSiteInfo() { + fill(0); + textAlign(CENTER); //set the text centered + textSize(40); //set text size + text("LightWater", width / 2, 40); //title + textSize(16); + text("www.freenove.com", width / 2, height - 20); //site +} \ No newline at end of file diff --git a/Processing/Sketchs/Sketch_11_1_1_SSD/IC74HC595.pde b/Processing/Sketchs/Sketch_11_1_1_SSD/IC74HC595.pde new file mode 100644 index 0000000..8277f59 --- /dev/null +++ b/Processing/Sketchs/Sketch_11_1_1_SSD/IC74HC595.pde @@ -0,0 +1,38 @@ +/***************************************************** + * Filename : IC74HC595 + * Description : class IC74HC595 + * auther : www.freenove.com + * modification: 2016/08/22 + *****************************************************/ +import processing.io.*; + +class IC74HC595 { + final int LSBFIRST = 1; + final int MSBFIRST = 2; + int dataPin, latchPin, clockPin; + public IC74HC595(int dPin, int lPin, int cPin) { + dataPin = dPin; + latchPin = lPin; + clockPin = cPin; + GPIO.pinMode(dataPin, GPIO.OUTPUT); + GPIO.pinMode(latchPin, GPIO.OUTPUT); + GPIO.pinMode(clockPin, GPIO.OUTPUT); + } + public void write(int order,int value) { + constrain(order,1,2); + GPIO.digitalWrite(latchPin,GPIO.LOW); + shiftOut(order,value); + GPIO.digitalWrite(latchPin,GPIO.HIGH); + } + private void shiftOut(int order, int val) { + for (int i = 0; i<8; i++) { + GPIO.digitalWrite(clockPin, GPIO.LOW); + if (order == LSBFIRST) { + GPIO.digitalWrite(dataPin, ((0x01&(val>>i))==0x01) ? GPIO.HIGH : GPIO.LOW); + } else if (order == MSBFIRST) { + GPIO.digitalWrite(dataPin, ((0x80&(val< 50/(0.05+mBar.progress)) { + lastMoveTime = millis(); + index++; + if (index > 9) { + index = 0; + } + } + ic.write(ic.MSBFIRST, numCode[index]); //write 74HC595 + showNum(index); //show the number in dispaly window +} +void showNum(int num) { + fill(0); + textSize(100); + textFont(mFont); //digiface font + textAlign(CENTER, CENTER); + text(num, width/2, height/2); +} +void mousePressed() { + if ( (mouseY< mBar.y+5) && (mouseY>mBar.y-5) ) { + mMouse = true; //the mouse click the progressBar + } +} +void mouseReleased() { + mMouse = false; +} +void mouseDragged() { + int a = constrain(mouseX, borderSize, width - borderSize); + float t = map(a, borderSize, width - borderSize, 0.0, 1.0); + if (mMouse) { + mBar.setProgress(t); + } +} +void titleAndSiteInfo() { + fill(0); + textAlign(CENTER); //set the text centered + textFont(createFont("", 100)); //default font + textSize(40); //set text size + text("Seven-segment Display", width / 2, 40); //title + textSize(16); + text("www.freenove.com", width / 2, height - 20); //site +} \ No newline at end of file diff --git a/Processing/Sketchs/Sketch_11_1_1_SSD/data/DigifaceWide-100.vlw b/Processing/Sketchs/Sketch_11_1_1_SSD/data/DigifaceWide-100.vlw new file mode 100644 index 0000000..66fa33c Binary files /dev/null and b/Processing/Sketchs/Sketch_11_1_1_SSD/data/DigifaceWide-100.vlw differ diff --git a/Processing/Sketchs/Sketch_11_1_1_SSD/data/DigifaceWide-48.vlw b/Processing/Sketchs/Sketch_11_1_1_SSD/data/DigifaceWide-48.vlw new file mode 100644 index 0000000..f14c129 Binary files /dev/null and b/Processing/Sketchs/Sketch_11_1_1_SSD/data/DigifaceWide-48.vlw differ diff --git a/Processing/Sketchs/Sketch_11_1_1_SSD/data/digifaw.ttf b/Processing/Sketchs/Sketch_11_1_1_SSD/data/digifaw.ttf new file mode 100644 index 0000000..59d1fb1 Binary files /dev/null and b/Processing/Sketchs/Sketch_11_1_1_SSD/data/digifaw.ttf differ diff --git a/Processing/Sketchs/Sketch_11_2_1_FDSSD/IC74HC595.pde b/Processing/Sketchs/Sketch_11_2_1_FDSSD/IC74HC595.pde new file mode 100644 index 0000000..8277f59 --- /dev/null +++ b/Processing/Sketchs/Sketch_11_2_1_FDSSD/IC74HC595.pde @@ -0,0 +1,38 @@ +/***************************************************** + * Filename : IC74HC595 + * Description : class IC74HC595 + * auther : www.freenove.com + * modification: 2016/08/22 + *****************************************************/ +import processing.io.*; + +class IC74HC595 { + final int LSBFIRST = 1; + final int MSBFIRST = 2; + int dataPin, latchPin, clockPin; + public IC74HC595(int dPin, int lPin, int cPin) { + dataPin = dPin; + latchPin = lPin; + clockPin = cPin; + GPIO.pinMode(dataPin, GPIO.OUTPUT); + GPIO.pinMode(latchPin, GPIO.OUTPUT); + GPIO.pinMode(clockPin, GPIO.OUTPUT); + } + public void write(int order,int value) { + constrain(order,1,2); + GPIO.digitalWrite(latchPin,GPIO.LOW); + shiftOut(order,value); + GPIO.digitalWrite(latchPin,GPIO.HIGH); + } + private void shiftOut(int order, int val) { + for (int i = 0; i<8; i++) { + GPIO.digitalWrite(clockPin, GPIO.LOW); + if (order == LSBFIRST) { + GPIO.digitalWrite(dataPin, ((0x01&(val>>i))==0x01) ? GPIO.HIGH : GPIO.LOW); + } else if (order == MSBFIRST) { + GPIO.digitalWrite(dataPin, ((0x80&(val< 50/(0.05+mBar.progress)) { + lastMoveTime = millis(); + index++; + if (index > 9999) { + index = 0; + } + } + showNum(index); //show the number in dispaly window +} +void showNum(int num) { + fill(0); + textSize(100); + textFont(mFont); //digiface font + textAlign(CENTER, CENTER); + text(nf(num,4,0), width/2, height/2); +} + +void displaySSD() { + while (true) { + display(index); + } +} +void selectDigit(int digit) { + GPIO.digitalWrite(digitPin[0], ((digit&0x08) == 0x08) ? GPIO.LOW : GPIO.HIGH); + GPIO.digitalWrite(digitPin[1], ((digit&0x04) == 0x04) ? GPIO.LOW : GPIO.HIGH); + GPIO.digitalWrite(digitPin[2], ((digit&0x02) == 0x02) ? GPIO.LOW : GPIO.HIGH); + GPIO.digitalWrite(digitPin[3], ((digit&0x01) == 0x01) ? GPIO.LOW : GPIO.HIGH); +} +void display(int dec) { + selectDigit(0x00); + ic.write(ic.MSBFIRST, numCode[dec%10]); + selectDigit(0x01); //select the first, and display the single digit + delay(1); //display duration + selectDigit(0x00); + ic.write(ic.MSBFIRST, numCode[dec%100/10]); + selectDigit(0x02); //select the second, and display the tens digit + delay(1); + selectDigit(0x00); + ic.write(ic.MSBFIRST, numCode[dec%1000/100]); + selectDigit(0x04); //select the third, and display the hundreds digit + delay(1); + selectDigit(0x00); + ic.write(ic.MSBFIRST, numCode[dec%10000/1000]); + selectDigit(0x08); //select the fourth, and display the thousands digit + delay(1); +} +void mousePressed() { + if ( (mouseY< mBar.y+5) && (mouseY>mBar.y-5) ) { + mMouse = true; //the mouse click the progressBar + } +} +void mouseReleased() { + mMouse = false; +} +void mouseDragged() { + int a = constrain(mouseX, borderSize, width - borderSize); + float t = map(a, borderSize, width - borderSize, 0.0, 1.0); + if (mMouse) { + mBar.setProgress(t); + } +} +void titleAndSiteInfo() { + fill(0); + textAlign(CENTER); //set the text centered + textFont(createFont("", 100)); //default font + textSize(40); //set text size + text("4-Digit 7-Segment Display", width / 2, 40); //title + textSize(16); + text("www.freenove.com", width / 2, height - 20); //site +} \ No newline at end of file diff --git a/Processing/Sketchs/Sketch_11_2_1_FDSSD/data/DigifaceWide-100.vlw b/Processing/Sketchs/Sketch_11_2_1_FDSSD/data/DigifaceWide-100.vlw new file mode 100644 index 0000000..66fa33c Binary files /dev/null and b/Processing/Sketchs/Sketch_11_2_1_FDSSD/data/DigifaceWide-100.vlw differ diff --git a/Processing/Sketchs/Sketch_11_2_1_FDSSD/data/DigifaceWide-48.vlw b/Processing/Sketchs/Sketch_11_2_1_FDSSD/data/DigifaceWide-48.vlw new file mode 100644 index 0000000..f14c129 Binary files /dev/null and b/Processing/Sketchs/Sketch_11_2_1_FDSSD/data/DigifaceWide-48.vlw differ diff --git a/Processing/Sketchs/Sketch_11_2_1_FDSSD/data/digifaw.ttf b/Processing/Sketchs/Sketch_11_2_1_FDSSD/data/digifaw.ttf new file mode 100644 index 0000000..59d1fb1 Binary files /dev/null and b/Processing/Sketchs/Sketch_11_2_1_FDSSD/data/digifaw.ttf differ diff --git a/Processing/Sketchs/Sketch_12_1_1_LEDMatrix/IC74HC595.pde b/Processing/Sketchs/Sketch_12_1_1_LEDMatrix/IC74HC595.pde new file mode 100644 index 0000000..2270b2d --- /dev/null +++ b/Processing/Sketchs/Sketch_12_1_1_LEDMatrix/IC74HC595.pde @@ -0,0 +1,38 @@ +/***************************************************** + * Filename : IC74HC595 + * Description : class IC74HC595 + * auther : www.freenove.com + * modification: 2016/08/22 + *****************************************************/ +import processing.io.*; + +class IC74HC595 { + final int LSBFIRST = 1; + final int MSBFIRST = 2; + int dataPin, latchPin, clockPin; + public IC74HC595(int dPin, int lPin, int cPin) { + dataPin = dPin; + latchPin = lPin; + clockPin = cPin; + GPIO.pinMode(dataPin, GPIO.OUTPUT); + GPIO.pinMode(latchPin, GPIO.OUTPUT); + GPIO.pinMode(clockPin, GPIO.OUTPUT); + } + public void write(int order, int value) { + constrain(order, 1, 2); + GPIO.digitalWrite(latchPin, GPIO.LOW); + shiftOut(order, value); + GPIO.digitalWrite(latchPin, GPIO.HIGH); + } + private void shiftOut(int order, int val) { + for (int i = 0; i<8; i++) { + GPIO.digitalWrite(clockPin, GPIO.LOW); + if (order == LSBFIRST) { + GPIO.digitalWrite(dataPin, ((0x01&(val>>i))==0x01) ? GPIO.HIGH : GPIO.LOW); + } else if (order == MSBFIRST) { + GPIO.digitalWrite(dataPin, ((0x80&(val<>=1; + } + } +} +void showNum() { + for (int j=0; j>=1; + } + } + } +} +void displayNum(String num) { + fill(0); + textSize(100); + textAlign(CENTER, CENTER); + text(num, width/2, height/2); +} +void mousePressed() { + if ( (mouseY< mBar.y+5) && (mouseY>mBar.y-5) ) { + mMouse = true; //the mouse click the progressBar + } +} +void mouseReleased() { + mMouse = false; +} +void mouseDragged() { + int a = constrain(mouseX, borderSize, width - borderSize); + float t = map(a, borderSize, width - borderSize, 0.0, 1.0); + if (mMouse) { + mBar.setProgress(t); + } +} +void titleAndSiteInfo() { + fill(0); + textAlign(CENTER); //set the text centered + textFont(createFont("", 100)); //default font + textSize(40); //set text size + text("LEDMatrix Display", width / 2, 40); //title + textSize(16); + text("www.freenove.com", width / 2, height - 20); //site +} \ No newline at end of file diff --git a/Processing/Sketchs/Sketch_13_1_1_LCD/Freenove_LCD.pde b/Processing/Sketchs/Sketch_13_1_1_LCD/Freenove_LCD.pde new file mode 100644 index 0000000..15ff51c --- /dev/null +++ b/Processing/Sketchs/Sketch_13_1_1_LCD/Freenove_LCD.pde @@ -0,0 +1,197 @@ +/***************************************************** + * Filename : Freenove_LCD + * Description : use I2C(pcf8574)control LCD1602 + * auther : www.freenove.com + * modification: 2016/08/24 + *****************************************************/ + +class Freenove_LCD1602 { + + final public int //HD44780U commands + CLEAR = 0x01, + HOME = 0x02, + ENTRY = 0x04, + CTRL = 0x08, + CDSHIFT= 0x10, + FUNC = 0x20, + CGRAM = 0x40, + DDRAM = 0x80; + + final public int //flags for display entry mode + ENTRY_SH = 0x01, + ENTRY_ID = 0x02; + + final public int //flags for display/cursor on/off control + BLINK_CTRL = 0x01, + CURSOR_CTRL = 0x02, + DISPLAY_CTRL= 0x04; + + final public int //flags function set + FUNC_F = 0x04, + FUNC_N = 0x08, + FUNC_DL = 0x10, + MOVERIGHT = 0x04, //flags for display/cursor shift + MOVELEFT = 0x00, + DISPLAYMOVE = 0x08, + CURSORMOVE = 0x00; + + final public int[] rowOff = {0x00, 0x40, 0x14, 0x54 }; + private int func = 0, control = 0; + PCF8574 pcf; + private int rows, cols, rsPin, enPin, rwPin; + int displayMode = 0; + + public Freenove_LCD1602(PCF8574 ipcf) { + pcf = ipcf; + rows = 2; + cols = 16; + rsPin = 0; //connect to PCF8574 module + enPin = 2; + rwPin = 1; + + pcf.digitalWrite(rsPin, 0); + pcf.digitalWrite(enPin, 0); + pcf.digitalWrite(rwPin, 0); + delay(35); + func = FUNC | FUNC_DL; //set 8-bit mode 3 times + put4Command(func>>4); + delay(35); + put4Command(func>>4); + delay(35); + put4Command(func>>4); + delay(35); + func = FUNC; //set 4-bit mode + put4Command(func>>4); + delay(35); + if (rows > 1) { + func = FUNC_N; + putCommand(func); + delay(35); + } + display(true); //lcd initializtion + lcdCursor(false); + cursorBlink(false); + + displayMode = ENTRY | ENTRY_ID; + putCommand(displayMode); + putCommand(CDSHIFT | MOVERIGHT); + backLightON(); + home(); + lcdClear(); + } + //for sending data/cmds + public void sendDataCmd(int data) { + int d4 = data & 0xf0; + pcf.writeByte(d4 | (pcf.currValue&0x0f)); + strobe(); + d4 = (data<<4) & 0xf0; + pcf.writeByte(d4 | (pcf.currValue&0x0f)); + strobe(); + } + //send command + public void putCommand(int cmd) { + pcf.digitalWrite(rsPin, 0); + sendDataCmd(cmd); + delay(2); + } + public void put4Command(int command) { + pcf.digitalWrite(rsPin, 0); + pcf.writeByte(((command<<4)&0xf0) | (pcf.currValue&0x0f)); + strobe(); + } + //pulse enable + public void strobe() { + pcf.digitalWrite(enPin, 1); + //delay(1); + //delayMicroseconds(50); + pcf.digitalWrite(enPin, 0); + //delay(1); + //delayMicroseconds(50); + } + //send a data byte to be displayed on the display. + public void putChar(char data) { + pcf.digitalWrite(rsPin, 1); + sendDataCmd(data); + } + //Send a string to be displayed on the display. + public void puts(String str) { + for (int i=0; i decounceTime) { + if (buttonIOState != nowButtonState) { + buttonIOState = nowButtonState; + changeState = true; + if (buttonIOState == GPIO.LOW) { + //btnState = PRESSED; + //keyValue = pin; + //println("Key is Pressed !! "); + } else if (buttonIOState == GPIO.HIGH) { + //println("Key is Released !! "); + } + } + } + switch(btnState) { + case IDLE: + if (changeState) { + changeState = false; + btnState = PRESSED; + holdTimer = millis(); + keyValue = pin; + isPressed = true; + } + break; + case PRESSED: + if (millis() - holdTimer > holdTime) { + btnState = HOLD; + keyValue = pin; + isPressed = true; + isHold = true; + } else if (changeState) { + changeState = false; + btnState = RELEASED; + } else { + keyValue = -1; + isPressed = false; + } + break; + case HOLD: + keyValue = pin; + isPressed = true; + isHold = true; + if (changeState) { + changeState = false; + btnState = RELEASED; + } + break; + case RELEASED: + keyValue = -1; + isPressed = false; + isHold = false; + btnState = IDLE; + break; + } + lastButtonIOState = nowButtonState; + } +} \ No newline at end of file diff --git a/Processing/Sketchs/Sketch_15_1_1_Relay/Sketch_15_1_1_Relay.pde b/Processing/Sketchs/Sketch_15_1_1_Relay/Sketch_15_1_1_Relay.pde new file mode 100644 index 0000000..b799864 --- /dev/null +++ b/Processing/Sketchs/Sketch_15_1_1_Relay/Sketch_15_1_1_Relay.pde @@ -0,0 +1,82 @@ +/***************************************************** + * Filename : Sketch_15_1_1_Relay + * Description : Control the Motor by Relay + * auther : www.freenove.com + * modification: 2016/08/30 + *****************************************************/ +import processing.io.*; + +int relayPin = 17; +int buttonPin = 18; +SingleKey skey = new SingleKey(buttonPin); +boolean relayState = false; +BUTTON btn; +float rotaSpeed = 0.02 * PI; //virtual fan's rotating speed, +float rotaPosition = 0; //motor position +void setup() { + size(640, 360); + GPIO.pinMode(relayPin, GPIO.OUTPUT); + btn = new BUTTON(90, height - 90, 50, 30); //define the button + btn.setBgColor(0, 255, 0); //set button color + btn.setText("OFF"); //set button text +} + +void draw() { + background(255); + titleAndSiteInfo(); //title and site information + + skey.keyScan(); //key scan + if (skey.isPressed) { //key is pressed? + relayAction(); + } + textAlign(RIGHT, CENTER); + text("RelayState: ", btn.x, btn.y+btn.h/2); + btn.create(); //create the button + if (relayState) { + rotaPosition += rotaSpeed; + } + if (rotaPosition >= 2*PI) { + rotaPosition = 0; + } + drawFan(rotaPosition); //show the virtual fan in Display window +} +//Draw a clover fan according to the stating angle +void drawFan(float angle) { + constrain(angle, 0, 2*PI); + fill(0); + for (int i=0; i<3; i++) { + arc(width/2, height/2, 200, 200, 2*i*PI/3+angle, (2*i+0.3)*PI/3+angle, PIE); + } + fill(0); + ellipse(width/2, height/2, 30, 30); + fill(128); + ellipse(width/2, height/2, 15, 15); +} +void relayAction() { + if (relayState) { + GPIO.digitalWrite(relayPin, GPIO.LOW); + relayState = false; + btn.setBgColor(255, 0, 0); + btn.setText("OFF"); + } else { + GPIO.digitalWrite(relayPin, GPIO.HIGH); + relayState = true; + btn.setBgColor(0, 255, 0); + btn.setText("ON"); + } +} +void mousePressed() { + if ((mouseY< btn.y+btn.h) && (mouseY>btn.y) + && (mouseX< btn.x+btn.w) && (mouseX>btn.x)) { // the mouse click the button + relayAction(); + } +} + +void titleAndSiteInfo() { + fill(0); + textAlign(CENTER); //set the text centered + textSize(40); //set text size + text("Relay & Motor", width / 2, 40); //title + textSize(16); + text("www.freenove.com", width / 2, height - 20); //site +} \ No newline at end of file diff --git a/Processing/Sketchs/Sketch_16_1_1_SteppingMotor/BUTTON.pde b/Processing/Sketchs/Sketch_16_1_1_SteppingMotor/BUTTON.pde new file mode 100644 index 0000000..4332306 --- /dev/null +++ b/Processing/Sketchs/Sketch_16_1_1_SteppingMotor/BUTTON.pde @@ -0,0 +1,51 @@ +/***************************************************** + * Filename : BUTTON + * Description : class BUTTON + * auther : www.freenove.com + * modification: 2016/08/22 + *****************************************************/ +class BUTTON { + public int x, y, w, h; + public String txt; + private int bgr, bgg, bgb; + private int tr, tg, tb; + public BUTTON(int ix, int iy, int iw, int ih) { + setPosition(ix, iy); + setSize(iw, ih); + setText("BTN"); + setBgColor(0, 0, 0); + setTextColor(255,255,255); + } + public void create() { + pushMatrix(); + translate(x,y); + fill(bgr, bgg, bgb); + rect(0, 0, w, h); + fill(tr, tg, tb); + textSize(min(w,h)/2); + textAlign(CENTER, CENTER); + text(txt, w/2, h/2); + popMatrix(); + } + public void setBgColor(int ir, int ig, int ib) { + bgr = ir; + bgg = ig; + bgb = ib; + } + public void setText(String str) { + txt = str; + } + public void setTextColor(int ir, int ig, int ib) { + tr = ir; + tg = ig; + tb = ib; + } + public void setSize(int iw, int ih) { + w = iw; + h = ih; + } + public void setPosition(int ix, int iy) { + x= ix; + y = iy; + } +} \ No newline at end of file diff --git a/Processing/Sketchs/Sketch_16_1_1_SteppingMotor/Sketch_16_1_1_SteppingMotor.pde b/Processing/Sketchs/Sketch_16_1_1_SteppingMotor/Sketch_16_1_1_SteppingMotor.pde new file mode 100644 index 0000000..ed7ea32 --- /dev/null +++ b/Processing/Sketchs/Sketch_16_1_1_SteppingMotor/Sketch_16_1_1_SteppingMotor.pde @@ -0,0 +1,96 @@ +/***************************************************** + * Filename : Sketch_16_1_1_SteppingMotor + * Description : Control the stepping motor + * auther : www.freenove.com + * modification: 2016/09/05 + *****************************************************/ +import processing.io.*; + +int[] pins = {18, 23, 24, 25}; //connect to motor phase A,B,C,D pins +BUTTON btn; //BUTTON Object, For controlling the direction of motor +SteppingMotor m = new SteppingMotor(pins); +float rotaSpeed = 0, rotaPosition = 0; //motor speed +boolean isMotorRun = true; //motor run/stop flag + +void setup() { + size(640, 360); + btn = new BUTTON(45, height - 90, 50, 30); //define the button + btn.setBgColor(0, 255, 0); //set button color + btn.setText("RUN"); //set button text + m.motorStart(); //start motor thread + rotaSpeed = 0.002 * PI; //virtual fan's rotating speed +} + +void draw() { + background(255); + titleAndSiteInfo(); //title and site information + btn.create(); //create the button + if (isMotorRun) { //motor is runnig + fill(0); + textAlign(LEFT,BOTTOM); + textSize(20); + if (m.dir == m.CW) { + text("CW",btn.x,btn.y); //text "CW " + rotaPosition+=rotaSpeed; + if (rotaPosition>=TWO_PI) { + rotaPosition = 0; + } + } else if (m.dir == m.CCW) { + text("CCW",btn.x,btn.y); //text "CCW" + rotaPosition-=rotaSpeed; + if (rotaPosition<=0) { + rotaPosition = TWO_PI; + } + } + } + if (m.steps<=0) { //if motor has stopped, + if (m.dir == m.CCW) { //change the direction ,restart. + m.moveSteps(m.CW, 1, 512); + } else if (m.dir == m.CW) { + m.moveSteps(m.CCW, 1, 512); + } + } + drawFan(rotaPosition); //show the virtual fan in Display window +} +//Draw a clover fan according to the stating angle +void drawFan(float angle) { + constrain(angle, 0, 2*PI); + fill(0); + for (int i=0; i<3; i++) { + arc(width/2, height/2, 200, 200, 2*i*PI/3+angle, (2*i+0.3)*PI/3+angle, PIE); + } + fill(0); + ellipse(width/2, height/2, 30, 30); + fill(128); + ellipse(width/2, height/2, 15, 15); +} + +void exit() { + m.motorStop(); + println("exit"); + System.exit(0); +} +void mousePressed() { + if ((mouseY< btn.y+btn.h) && (mouseY>btn.y) + && (mouseX< btn.x+btn.w) && (mouseX>btn.x)) { // the mouse click the button + if (isMotorRun) { + isMotorRun = false; + btn.setBgColor(255, 0, 0); + btn.setText("STOP"); + m.motorStop(); + } else { + isMotorRun = true; + btn.setBgColor(0, 255, 0); + btn.setText("RUN"); + m.motorRestart(); + } + } +} +void titleAndSiteInfo() { + fill(0); + textAlign(CENTER); //set the text centered + textSize(40); //set text size + text("Motor", width / 2, 40); //title + textSize(16); + text("www.freenove.com", width / 2, height - 20); //site +} \ No newline at end of file diff --git a/Processing/Sketchs/Sketch_16_1_1_SteppingMotor/SteppingMotor.pde b/Processing/Sketchs/Sketch_16_1_1_SteppingMotor/SteppingMotor.pde new file mode 100644 index 0000000..890e20a --- /dev/null +++ b/Processing/Sketchs/Sketch_16_1_1_SteppingMotor/SteppingMotor.pde @@ -0,0 +1,112 @@ +/***************************************************** + * Filename : SteppingMotor + * Description : class SteppingMotor + * auther : www.freenove.com + * modification: 2016/08/31 + *****************************************************/ + +class SteppingMotor { + + final int[] CWStep = {0x01, 0x02, 0x04, 0x08}; //4 phase 4 steps power supply CW + final int[] CCWStep = {0x08, 0x04, 0x02, 0x01}; //4 phase 4 steps power supply CCW + final int CW = 1, CCW=2; + int[] motorPins; //define pins connected to four phase ABCD of stepping motor + boolean isDisable = false; + int dir= CCW, ms=1, steps=-1; + myThread mt = new myThread(); + Thread t = new Thread(mt); + public SteppingMotor(int[] mPins) { + motorPins = mPins; + for (int i=0; i<4; i++) { + GPIO.pinMode(motorPins[i], GPIO.OUTPUT); + } + } + public void motorStart() { + t.start(); + } + //continuos rotation function,the parameter steps spectfies the rotation steps, + //every four step is a steps(period) + public void moveSteps(int idir, int ims, int isteps) { + dir= idir; + ms=ims; + steps=isteps; + motorRestart(); + } + //used to motor stop rotating + public void motorStop() { + isDisable = true; + for (int i=0; i<4; i++) { + GPIO.digitalWrite(motorPins[i], GPIO.LOW); + } + } + public void motorRestart() { + isDisable = false; + synchronized(t) { + try { + t.notifyAll(); + } + catch(Exception e) { + println(e); + } + } + } + //It's same to moveOnePeriod() + public void moveFourStep(int idir, int ims) { + moveOnePeriod(idir, ims); + } + //drive the stepping motor to take four steps,four steps is a period + public void moveOnePeriod(int idir, int ims) { + if (isDisable) { + println("Motor is disabled! Please enbale it!"); + motorStop(); + return; + } + for (int j=0; j<4; j++) { //cycle according to power supply order + for (int i=0; i<4; i++) { //assign to each pin ,a total of 4 pins + if (idir == CW) { //CW + GPIO.digitalWrite(motorPins[i], (CWStep[j] == (1<run:"+e); + } + } + } + if (--steps>-1) { + moveOnePeriod(dir, ms); + } else { + try { + motorStop(); + } + catch(Exception e) { + println("--->run:"+e); + } + } + } + } + } +} \ No newline at end of file diff --git a/Processing/Sketchs/Sketch_17_1_1_Calculator/Calculator.pde b/Processing/Sketchs/Sketch_17_1_1_Calculator/Calculator.pde new file mode 100644 index 0000000..455ddc0 --- /dev/null +++ b/Processing/Sketchs/Sketch_17_1_1_Calculator/Calculator.pde @@ -0,0 +1,127 @@ +/***************************************************** + * Filename : Calculator + * Description : class Calculator + * auther : www.freenove.com + * modification: 2016/09/02 + *****************************************************/ +import java.math.BigDecimal; +class Calculator { + Keypad keypad; + + double result=0; //Calculate result + String txt = ""; // + String contentStr = ""; //Display string + char mark; //operate mark + final int NUM=1, MARK=2, RESULT=3, BLANK = 4; //Current content + int currentContent = BLANK; // + boolean calcul_isStandBy = true; //Star and Clear + char kkey = ' '; //the key value + public Calculator(Keypad kp) { + keypad = kp; + } + public void process() { + kkey = kp.getKey(); + if (kkey != keypad.NO_KEY) { //if there is a key is pressed + calcul_isStandBy = false; + if ((kkey > 0x2F)&&(kkey < 0x3A)) { //key code is 0-9 + if (currentContent == RESULT) { //current Content is last results,clear + txt=""; + txt+=kkey; //Store the key code + currentContent=NUM; + } else { + txt+=kkey; + currentContent=NUM; + } + } else if ((kkey == '+') || (kkey == '-')||(kkey == '*')||(kkey == '/')) { + if (currentContent == RESULT) { //last results,Use it to make continuous calculations + txt = ""+result; + txt +=kkey; + } else if (currentContent==MARK) { //change mark + txt = txt.substring(0, txt.length()-1)+kkey; + } else if (currentContent==BLANK) { //0 + mark + txt+=("0"+kkey); + } else { + txt +=kkey; + } + currentContent=MARK; + } else if (kkey == '=') { //if the key code is "=" + if (currentContent == RESULT) { //Keep last results + txt+=("="+result); + currentContent = RESULT; + } else if (currentContent == BLANK) { //No active,keep standby + calcul_isStandBy = true; + currentContent = BLANK; + } else { + if (currentContent==MARK) { //if the last char is a MARK,delete it. + txt = txt.substring(0, txt.length()-1); + } + if (txt.charAt(0) == '-') { //negative number,add "0" in start bit + txt = "0".concat(txt); + } + result = parse(txt); //calculate the result + txt+=("="+result); + currentContent = RESULT; + } + } else if (kkey == 'C') { //clear + cclear(); + } + } + if (calcul_isStandBy) { + contentStr = "0"; + } else { + contentStr = txt; + } + } + public void cclear() { //Clear all datas, make calculator standby + txt = ""; + calcul_isStandBy = true; + result = 0; + currentContent = BLANK; + } + public double parse(String content) { //parse processing + int index = content.indexOf("+"); + if (index != -1) { + BigDecimal b1 = new BigDecimal(parse(content.substring(0, index))); + BigDecimal b2 = new BigDecimal(parse(content.substring(index+1))); + return rround(b1.add(b2).doubleValue(),6); + //return parse(content.substring(0, index)) + parse(content.substring(index+1)); + } + index = content.lastIndexOf("-"); + if (index != -1) { + BigDecimal b1 = new BigDecimal(parse(content.substring(0, index))); + BigDecimal b2 = new BigDecimal(parse(content.substring(index+1))); + return rround(b1.subtract(b2).doubleValue(),6); + //return parse(content.substring(0, index)) - parse(content.substring(index+1)); + } + index = content.indexOf("*"); + if (index != -1) { + //println("* : "+content.substring(0, index) +" " + content.substring(index+1)); + BigDecimal b1 = new BigDecimal(parse(content.substring(0, index))); + BigDecimal b2 = new BigDecimal(parse(content.substring(index+1))); + return rround(b1.multiply(b2).doubleValue(),6); + //return parse(content.substring(0, index)) * parse(content.substring(index+1)); + } + index = content.lastIndexOf("/"); + if (index != -1) { + //println("/ : "+content.substring(0, index) +" " + content.substring(index+1)); + BigDecimal b1 = new BigDecimal(parse(content.substring(0, index))); + BigDecimal b2 = new BigDecimal(parse(content.substring(index+1))); + return b1.divide(b2,6,BigDecimal.ROUND_HALF_UP).doubleValue(); + //return parse(content.substring(0, index)) / parse(content.substring(index+1)); + } + Double result = 0d; + //try { + result = Double.parseDouble(content); + //} + //catch(Exception e) { + // println(e+" \n txt: "+txt); + //} + //println("result: "+result); + return result; + } + public double rround(double d,int len){ //rounding + BigDecimal b1 = new BigDecimal(d); + BigDecimal b2 = new BigDecimal(1); + return b1.divide(b2,len,BigDecimal.ROUND_HALF_UP).doubleValue(); + } +} \ No newline at end of file diff --git a/Processing/Sketchs/Sketch_17_1_1_Calculator/DrawKeypad.pde b/Processing/Sketchs/Sketch_17_1_1_Calculator/DrawKeypad.pde new file mode 100644 index 0000000..dcf67d6 --- /dev/null +++ b/Processing/Sketchs/Sketch_17_1_1_Calculator/DrawKeypad.pde @@ -0,0 +1,68 @@ +/***************************************************** + * Filename : drawKeypad + * Description : function drawKeypad + * auther : www.freenove.com + * modification: 2016/09/02 + *****************************************************/ + +final int gap =10; +final int kSize = 50; +final int kpSize = kSize*4+3*gap+gap*4; +boolean keyIsPressed = false; +int changeColorCnt = 0; +int changeKeyCode = 0; +void drawKeypad(int x, int y) { + pushMatrix(); + translate(x, y); + noStroke(); + fill(0); + rect(0, 0, kpSize, kpSize, 10); + + strokeWeight(4); + stroke(255); + fill(0); + rect(gap, gap, kpSize-2*gap, kpSize-2*gap, 10); + + strokeWeight(4); + stroke(255); + //fill(0,255,0); + textSize(40); + textAlign(CENTER, CENTER); + for (int i=0; i<4; i++) { + for (int j=0; j<4; j++) { + if (((i<3)&&(j<3))||((i==3)&&(j==1))) { //blue and red + fill(64, 64, 255); + } else { + fill(255, 64, 64); + } + if (cc.kkey == keys[4*i+j]) { //if any key is pressed,fill in green + changeKeyCode = 4*i+j; + fill(64, 255, 64); + keyIsPressed = true; + changeColorCnt = 0; + } else if (keyIsPressed && (changeKeyCode == 4*i+j)) { //Keep green for some time + changeColorCnt ++ ; + if (changeColorCnt>20) { + changeColorCnt = 0; + keyIsPressed = false; + } + fill(64, 255, 64); + } + rect(2*gap+j*(kSize+gap), 2*gap+i*(kSize+gap), kSize, kSize, 5); //draw key + fill(255); //draw key code of key + text(keys[4*i+j], (2*gap+j*(kSize+gap)+kSize/2), (2*gap+i*(kSize+gap)+kSize/2)); + } + } + popMatrix(); +} + +void drawDisplay(String content) { + stroke(0); + strokeWeight(4); + fill(255); + rect(0, 0, width, 50); //Display area + fill(0); + textSize(40); + textAlign(RIGHT, TOP); + text(content, width-5, 5); //Display content +} \ No newline at end of file diff --git a/Processing/Sketchs/Sketch_17_1_1_Calculator/Key.pde b/Processing/Sketchs/Sketch_17_1_1_Calculator/Key.pde new file mode 100644 index 0000000..9b420e6 --- /dev/null +++ b/Processing/Sketchs/Sketch_17_1_1_Calculator/Key.pde @@ -0,0 +1,29 @@ +/***************************************************** + * Filename : Key + * Description : class Key + * auther : www.freenove.com + * modification: 2016/09/02 + *****************************************************/ + +//class Key:Define some of the properties of Key +class Key { + final char NO_KEY = '\0'; + //Defines the four states of Key + final int IDLE = 0, + PRESSED = 1, + HOLD = 2, + RELEASED = 3; + //define OPEN and CLOSED + final int OPEN = 0, + CLOSED = 1; + char kchar; + int kstate, kcode; + boolean stateChanged; + //constructor + public Key() { + kchar = NO_KEY; + kstate = IDLE; + kcode = -1; + stateChanged = false; + } +} \ No newline at end of file diff --git a/Processing/Sketchs/Sketch_17_1_1_Calculator/Keypad.pde b/Processing/Sketchs/Sketch_17_1_1_Calculator/Keypad.pde new file mode 100644 index 0000000..90f0fff --- /dev/null +++ b/Processing/Sketchs/Sketch_17_1_1_Calculator/Keypad.pde @@ -0,0 +1,212 @@ +/***************************************************** + * Filename : Keypad + * Description : class Keypad + * auther : www.freenove.com + * modification: 2016/09/02 + *****************************************************/ + +class Keypad { + final char NO_KEY = '\0'; + final int IDLE = 0, + PRESSED = 1, + HOLD = 2, + RELEASED = 3; + //define OPEN and CLOSED + final int OPEN = 0, + CLOSED = 1; + final int LIST_MAX = 10, //Max number of keys on the active list. + MAPSIZE = 10;//MAPSIZE is the number of rows (times 16 columns) + int[] bitMap = new int[MAPSIZE]; + Key[] key = new Key[LIST_MAX]; + int holdTime = 500, //key hold time + holdTimer = 0; + int[] rowPins, colPins; + int numRows, numCols; + char[] keymap; + int debounceTime = 10; //10ms + long startTime = 0; + public Keypad(char[] usrKeyMap, int[] row_Pins, int[] col_Pins) { + keymap = usrKeyMap; + rowPins = row_Pins; + colPins = col_Pins; + numRows = rowPins.length; + numCols = colPins.length; + for (int i=0; i debounceTime) { + scanKeys(); + keyActivity = updateList(); + startTime = millis(); + } + return keyActivity; + } + //set pins for input/output + void setPinMode() { + for (int i=0; i -1) { + nextKeyState(idx, button); + } + // Key is NOT on the list so add it. + if ((idx == -1)&& button) { + for (int i=0; iholdTime) // Waiting for a key HOLD... + transitionTo (idx, HOLD); + else if (!button) // or for a key to be RELEASED. + transitionTo (idx, RELEASED); + break; + case HOLD: + if (!button) { + transitionTo (idx, RELEASED); + } + break; + case RELEASED: + transitionTo (idx, IDLE); + break; + } + } + private void transitionTo(int idx, int nextState) { + key[idx].kstate = nextState; + key[idx].stateChanged = true; + } + // Search by code for a key in the list of active keys. + // Returns -1 if not found or the index into the list of active keys. + private int findInList(int keycode) { + for (int i=0; i>n)&1) == 1) { + return true; + } else { + return false; + } + } +} \ No newline at end of file diff --git a/Processing/Sketchs/Sketch_17_1_1_Calculator/Sketch_17_1_1_Calculator.pde b/Processing/Sketchs/Sketch_17_1_1_Calculator/Sketch_17_1_1_Calculator.pde new file mode 100644 index 0000000..6243522 --- /dev/null +++ b/Processing/Sketchs/Sketch_17_1_1_Calculator/Sketch_17_1_1_Calculator.pde @@ -0,0 +1,35 @@ +/***************************************************** + * Filename : Sketch_17_1_1_MatrixKeypad + * Description : Make a calculator using the keypad + * auther : www.freenove.com + * modification: 2016/09/02 + *****************************************************/ +import processing.io.*; + +final static char[] keys = { //key code + '1', '2', '3', '+', + '4', '5', '6', '-', + '7', '8', '9', '*', + 'C', '0', '=', '/' }; +final int[] rowsPins = {18, 23, 24, 25}; //Connect to the row pinouts of the keypad +final int[] colsPins = {10, 22, 27, 17}; //Connect to the column pinouts of the keypad +Keypad kp = new Keypad(keys, rowsPins, colsPins); //class Object +Calculator cc = new Calculator(kp); //class Object +void setup() { + size(640, 360); +} +void draw() { + background(102); + titleAndSiteInfo(); //Tile and site information + cc.process(); //Get key and processing + drawDisplay(cc.contentStr); //Draw display area and content + drawKeypad(width-kpSize, 70); //draw virtual Keypad +} +void titleAndSiteInfo() { + fill(0); + textAlign(CENTER); //set the text centered + textSize(40); //set text size + text("Calculator", width / 4, 200); //title + textSize(20); + text("www.freenove.com", width / 4, height - 20); //site +} \ No newline at end of file diff --git a/Processing/Sketchs/Sketch_18_1_1_SenseLED/Sketch_18_1_1_SenseLED.pde b/Processing/Sketchs/Sketch_18_1_1_SenseLED/Sketch_18_1_1_SenseLED.pde new file mode 100644 index 0000000..901688d --- /dev/null +++ b/Processing/Sketchs/Sketch_18_1_1_SenseLED/Sketch_18_1_1_SenseLED.pde @@ -0,0 +1,38 @@ +/***************************************************** + * Filename : Sketch_18_1_1_SenseLED + * Description : Control the led by Infare motion sensor + * auther : www.freenove.com + * modification: 2016/08/22 + *****************************************************/ +import processing.io.*; + +final int sensorPin = 17; //connect to sensor pin +final int ledPin = 18; //connect to led pin +void setup() { + size(640,360); //window size + GPIO.pinMode(sensorPin, GPIO.INPUT); + GPIO.pinMode(ledPin, GPIO.OUTPUT); +} + +void draw() { + background(102); + titleAndSiteInfo(); + //if read sensor for high level + if (GPIO.digitalRead(sensorPin) == GPIO.HIGH) { + GPIO.digitalWrite(ledPin, GPIO.HIGH); //led on + fill(64,255,64); //fill in green + } else { + GPIO.digitalWrite(ledPin, GPIO.LOW); //led off + fill(255); //fill in white + } + ellipse(width/2,height/2,height/2,height/2); +} + +void titleAndSiteInfo() { + fill(0); + textAlign(CENTER); //set the text centered + textSize(40); //set text size + text("SENSE LED", width / 2, 40); //title + textSize(16); + text("www.freenove.com", width / 2, height - 20); //site +} \ No newline at end of file diff --git a/readme.txt b/readme.txt index 7aa6bb0..7c620cc 100644 --- a/readme.txt +++ b/readme.txt @@ -4,8 +4,10 @@ References The references for this product includes the following folders and files: Datasheet Datasheet of electronic components and modules Code Code for Raspberry Pi + Processing Sketches for Interacting with Processing projects Readme.txt Instructions Tutorial.pdf Tutorial + Processing.pdf Tutorial for Interacting with Processing You can click the green Clone or download button in this page, then click Download ZIP to get all these files in zip format. If you have any difficulties, you can send email to our support for help.