Today we talk about Seeed Studio Grove Modules and using them with our FEZ products.
Here is the code:
// original code https://github.com/Seeed-Studio/Grove_LCD_RGB_Backlight
using System;
using System.Threading;
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using GHI.IO;
namespace grove_test
{
public static class rgb_lcd
{
static SoftwareI2CBus I2C = new SoftwareI2CBus(GHI.Pins.FEZCobraIII.Gpio.D19, GHI.Pins.FEZCobraIII.Gpio.D18);
static byte LCD_ADDRESS=(0x7c>>1);
static void i2c_send_byte(byte dta)
{
int written, read;
byte[] wb = new byte[2];
byte[] rb = new byte[2];
wb[0] = dta;
I2C.WriteRead(LCD_ADDRESS, wb, 0, 1, rb, 0, 0, out written, out read);
}
static void i2c_send_byteS(byte[] dta, byte len)
{
int written, read;
//byte[] wb = new byte[2];
byte[] rb = new byte[2];
//wb[0] = dta;
I2C.WriteRead(LCD_ADDRESS, dta, 0, len, rb, 0, 0, out written, out read);
}
static byte _displayfunction;
static byte _displaycontrol;
static byte _displaymode;
static byte _numlines, _currline;
static byte LCD_CLEARDISPLAY = 0x01;
static byte LCD_RETURNHOME = 0x02;
static byte LCD_ENTRYMODESET = 0x04;
static byte LCD_DISPLAYCONTROL = 0x08;
static byte LCD_CURSORSHIFT = 0x10;
static byte LCD_FUNCTIONSET = 0x20;
static byte LCD_SETCGRAMADDR = 0x40;
static byte LCD_SETDDRAMADDR = 0x80;
static byte LCD_DISPLAYON = 0x04;
static byte LCD_DISPLAYOFF = 0x00;
static byte LCD_CURSORON = 0x02;
static byte LCD_CURSOROFF = 0x00;
static byte LCD_BLINKON = 0x01;
static byte LCD_BLINKOFF = 0x00;
static byte LCD_ENTRYRIGHT = 0x00;
static byte LCD_ENTRYLEFT = 0x02;
static byte LCD_ENTRYSHIFTINCREMENT = 0x01;
static byte LCD_ENTRYSHIFTDECREMENT = 0x00;
static byte REG_MODE1 = 0x00;
static byte REG_MODE2 = 0x01;
static byte REG_OUTPUT = 0x08;
public static void begin(byte cols, byte lines, byte dotsize)
{
if (lines > 1)
{
_displayfunction |= 0x08;// LCD_2LINE;
}
_numlines = lines;
_currline = 0;
// for some 1 line displays you can select a 10 pixel high font
if ((dotsize != 0) && (lines == 1))
{
_displayfunction |= 0x04;// LCD_5x10DOTS;
}
// SEE PAGE 45/46 FOR INITIALIZATION SPECIFICATION!
// according to datasheet, we need at least 40ms after power rises above 2.7V
// before sending commands. Arduino can turn on way befer 4.5V so we'll wait 50
//delayMicroseconds(50000);
Thread.Sleep(50);
// this is according to the hitachi HD44780 datasheet
// page 45 figure 23
// Send function set command sequence
command((byte)(LCD_FUNCTIONSET | _displayfunction));
//delayMicroseconds(4500); // wait more than 4.1ms
Thread.Sleep(5);
// second try
command((byte)(LCD_FUNCTIONSET | _displayfunction));
//delayMicroseconds(150);
Thread.Sleep(1);
// third go
command((byte)(LCD_FUNCTIONSET | _displayfunction));
// finally, set # lines, font size, etc.
command((byte)(LCD_FUNCTIONSET | _displayfunction));
// turn the display on with no cursor or blinking default
_displaycontrol = (byte)(LCD_DISPLAYON | LCD_CURSOROFF | LCD_BLINKOFF);
display();
// clear it off
clear();
// Initialize to default text direction (for romance languages)
_displaymode = (byte)(LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT);
// set the entry mode
command((byte)(LCD_ENTRYMODESET | _displaymode));
// backlight init
setReg(REG_MODE1, 0);
// set LEDs controllable by both PWM and GRPPWM registers
setReg(REG_OUTPUT, 0xFF);
// set MODE2 values
// 0010 0000 -> 0x20 (DMBLNK to 1, ie blinky mode)
setReg(REG_MODE2, 0x20);
//setColorWhite();
setRGB(255, 0, 100);
}
/********** high level commands, for the user! */
static void clear()
{
command(LCD_CLEARDISPLAY); // clear display, set cursor position to zero
//delayMicroseconds(2000); // this command takes a long time!
Thread.Sleep(2);
}
static void home()
{
command(LCD_RETURNHOME); // set cursor position to zero
//delayMicroseconds(2000); // this command takes a long time!
Thread.Sleep(2);
}
public static void setCursor(byte col, byte row)
{
col = (byte)(row == 0 ? (col | 0x80) : (col | 0xc0));
byte[] dta=new byte[2] { 0x80, col };
i2c_send_byteS(dta, 2);
}
// Turn the display on/off (quickly)
static void noDisplay()
{
_displaycontrol &= (byte)~LCD_DISPLAYON;
command((byte)(LCD_DISPLAYCONTROL | _displaycontrol));
}
static void display()
{
_displaycontrol |= LCD_DISPLAYON;
command((byte)(LCD_DISPLAYCONTROL | _displaycontrol));
}
// Control the backlight LED blinking
static void blinkLED()
{
// blink period in seconds = (<reg 7> + 1) / 24
// on/off ratio = <reg 6> / 256
setReg(0x07, 0x17); // blink every second
setReg(0x06, 0x7f); // half on, half off
}
static void noBlinkLED()
{
setReg(0x07, 0x00);
setReg(0x06, 0xff);
}
/*********** mid level commands, for sending data/cmds */
// send command
static void command(byte value)
{
byte[] dta = new byte[2] { 0x80, value };
i2c_send_byteS(dta, 2);
}
// send data
public static void write(byte value)
{
byte[] dta = new byte[2] { 0x40, value };
i2c_send_byteS(dta, 2);
//return 1; // assume sucess
}
public static void write(string s)
{
for (int i = 0; i < s.Length; i++)
write((byte)s[i]);
}
static void setReg(byte addr, byte dta)
{
int written, read;
byte[] wb = new byte[2];
byte[] rb = new byte[2];
wb[0] = addr;
wb[1] = dta;
I2C.WriteRead((0xc4 >> 1), wb, 0, 2, rb, 0, 0, out written, out read);
}
public static void setRGB(byte r, byte g, byte b)
{
byte REG_RED = 0x04; // pwm2
byte REG_GREEN = 0x03; // pwm1
byte REG_BLUE = 0x02; // pwm0
setReg(REG_RED, r);
setReg(REG_GREEN, g);
setReg(REG_BLUE, b);
}
}
public class Program
{
static void Bounce()
{
Bitmap LCD = new Bitmap(480, 272);
int x = 50, y = 50;
int dx = 1, dy = 1;
int sx = 5, sy = 5;
PulseFeedback PF = new PulseFeedback(PulseFeedback.Mode.EchoDuration, true, 10, GHI.Pins.FEZCobraIII.Gpio.D2);
PF.ResistorMode = Port.ResistorMode.PullDown;
while (true)
{
LCD.Clear();
LCD.DrawEllipse(Microsoft.SPOT.Presentation.Media.Color.White, x, y, 10, 10);
LCD.Flush();
x += (dx * sx);
y += (dy * sy);
if (x < 0 || x > 480)
dx *= -1;
if (y < 0 || y > 272)
dy *= -1;
int speed= (int) (PF.Read() / 100);
if (speed > 50)
speed = 50;
sx = sy = speed;
//Debug.Print("feed" + PF.Read());
Thread.Sleep(50);
}
}
public static void Main()
{
// make a ball bounce in a seperat thread
Thread BounceThread = new Thread(Bounce);
BounceThread.Start();
// the main program thread, the grove demo
AnalogInput A0 = new AnalogInput(GHI.Pins.FEZCobraIII.AnalogInput.D14);
OutputPort D3 = new OutputPort(GHI.Pins.FEZCobraIII.Gpio.D3, false);
OutputPort D4 = new OutputPort(GHI.Pins.FEZCobraIII.Gpio.D4, true);
InputPort D8 = new InputPort(GHI.Pins.FEZCobraIII.Gpio.D8, false, Port.ResistorMode.PullUp);
Random r = new Random();
// test the RGB LCD. all I2C
rgb_lcd.begin(6, 2, 0);
Thread.Sleep(300);
rgb_lcd.write((byte)'G');
rgb_lcd.write((byte)'H');
rgb_lcd.write((byte)'I');
while(true)
{
int a = A0.ReadRaw()/4;
double temperature;
int B = 3975;
float resistance = (float)(1023 - a) * 10000 / a;
temperature = 1 / (System.Math.Log(resistance / 10000) / B + 1 / 298.15) - 273.15;
temperature = temperature / 2;
rgb_lcd.setCursor(0, 0);
rgb_lcd.write("Temp: "+ temperature.ToString());
if (temperature > 30)
D4.Write(true);
else
D4.Write(false);
if (temperature > 33)
D3.Write(true);
else
D3.Write(false);
if(D8.Read())
{
rgb_lcd.setRGB((byte)r.Next(), (byte)r.Next(), (byte)r.Next());
}
Thread.Sleep(300);
}
}
}
}
Yeah I am special
We redid the studio for better lighting. Hopefully future videos will look better.
Your limit checks are bounded incorrectly, since the “valid” range of display values is 0 to 479 (or 0 to 271 height). Besides the fact that you should use the dynamic screen size from the framework instead of hardcoding a value there and in your bitmap dimension.
if (x < 0 || x > 479)
dx *= -1;
if (y < 0 || y > 271)
dy *= -1;
Hi Gus
I use GHI and Grove gear for teaching and personal projects, including my electric longboard. (It does >30Kph with a range of 10-15K depending on speed & terrain.)
For my prototype I modified a 5CM Grove cable so I could use Grove I2C modules with the dedicated I2C pins on my Fez Lemur.
The Seeedstudio base shields (plus other plug n play systems from vendors like electow.com, elecfreaks.com) are designed to work with *duino devices with the I2C on A4/A5 or the two dedicated pins (like the Arduino Uno R3 devices) it would be great if some future *duino formfactor GHI devices used these pinouts.
@ kiwiBryn
blog.devmobile.co.nz