Blog 20

From BitWizard WIKI
Revision as of 11:17, 30 November 2015 by Cartridge1987 (talk | contribs) (!BETA! Understanding the SPI example code)

Jump to: navigation, search

!BETA!Understanding the I2C example code

Hello, in this post I want to give explanation tips for the example I2C code you can see LCD. A link to the code:

I would recommend if you are new to arduino to search stuff you are unfamiliar with on the internet.
On Arduino's reference page you can find a lot of the commands well explained.

What does the code? The code is a counter, that counts one up of the previous code. So, you can say it counts the seconds it is on.

The full code:

#include <Wire.h> 

void setup()
{
  Wire.begin(); // join i2c bus (address optional for master)
} 

#define I2C_LCD_ADDR (0x82>>1) 

void lcd_cls (void)
{
  Wire.beginTransmission(I2C_LCD_ADDR); // transmit to device #4
  Wire.send (0x10);                    // Send dummy byte to port 10: clear screen. 
  Wire.send (0);        
  Wire.endTransmission();    // stop transmitting
}

void lcd_print (char *str)
{
  Wire.beginTransmission(I2C_LCD_ADDR); // transmit to device #4
  Wire.send (0x0);                    // Send dummy byte to port 10: clear screen. 
  Wire.send (str);        
  Wire.endTransmission();    // stop transmitting
}

void lcd_gotoxy (int x, int y)
{
  Wire.beginTransmission(I2C_LCD_ADDR); // transmit to device #4
  Wire.send (0x11);                    // Send dummy byte to port 10: clear screen. 
  Wire.send ((y << 5) | (x&0x1f));        
  Wire.endTransmission();    // stop transmitting
}

void loop()
{
  char buf[0x10];
  static int x;
 
  lcd_cls ();
 
  lcd_gotoxy (x&0xf,1);
  lcd_print ("*");
  lcd_gotoxy (0,0);
   
  sprintf (buf, "x is: %d", x++);
  lcd_print (buf);

  delay(1000);
}

Open I2C Library:

#include <Wire.h> 

Set up the contact with I2C Bus.

void setup()
{
  Wire.begin(); // join i2c bus (address optional for master)
} 

Gives the address location.

#define I2C_LCD_ADDR (0x82>>1) 

The 0x82 is in this example bit shifted(>>) to the right with one. Bit shifting in this example let a the bits go to the right. So easy example with a 4 bits: 0010 will become 0001. The hexadecimal result should be: 0x41. This is an easy technique if you know the address value, but don't want to figure out what the hexadecimal value is when you divide it with 2.

(0x82>>1)

(cls = clear screen) This part can be called later in the script. The begin transmission write to the address given from I2C_LCD_ADDR with register 0x10 and the value 0. This will clear the screen of the lcd. After that is stops transmitting data.

void lcd_cls (void)
{
  Wire.beginTransmission(I2C_LCD_ADDR); // transmit to device #4
  Wire.send (0x10);                    // Send dummy byte to port 10: clear screen. 
  Wire.send (0);        
  Wire.endTransmission();    // stop transmitting
}

This will put characters in a string. He again start transmitting to the address to register 0x0 and with the value given in the str.

void lcd_print (char *str)
{
  Wire.beginTransmission(I2C_LCD_ADDR); // transmit to device #4
  Wire.send (0x0);                    // Send dummy byte to port 10: clear screen. 
  Wire.send (str);        
  Wire.endTransmission();    // stop transmitting
}

This will make contact to int x and int y. It will start transmitting to the address and talk to register 0x11. The bits value of y will be shifted 5 to the left. The '|' is an or function, what it does is that it wants one of or both of the two be 1. After that it will stop transmitting.

void lcd_gotoxy (int x, int y)
{
  Wire.beginTransmission(I2C_LCD_ADDR); // transmit to device #4
  Wire.send (0x11);                    // Send dummy byte to port 10: clear screen. 
  Wire.send ((y << 5) | (x&0x1f));        
  Wire.endTransmission();    // stop transmitting
}

The loop will make it that the arduino, will repeatedly repeat the code. The character in the array will get the in the string the value of '0x10'. The static make that x will only work with one function, and will stay with the same value. After that it makes contact with the cls function.

void loop()
{
  char buf[0x10];
  static int x;
 
  lcd_cls ();
 

Gives to lcd_gotoxy x & 0xf, and to the other one the value 1. Gives to lcd_print to the str, with 0x10. Gives to lcd_gotoxy the value 0,0 to clean it.

 lcd_gotoxy (x&0xf,1);
 lcd_print ("*");
 lcd_gotoxy (0,0);
  

It will print on the serial monitor(CTRL+M) with the array given value and will counts with x++ one more on the number. Let's the lcd print the given value in buf(Group or arrays with bytes). After that it waits 1000miliseconds = 1 seconds.

  sprintf (buf, "x is: %d", x++);
  lcd_print (buf);

  delay(1000);
}

Mistake in the code is in the comments, that there is several times said that: // Send dummy byte to port 10: clear screen. This only happens with the first one.


!BETA! Understanding the SPI example code

Here I will give extra information, about the SPI example you can see at LCD:
Arduino lcd SPI demo

I won't copy paste the full code, this time because I don't want to fill up the page. While I only explaining special parts of the code.

What does this code do? This code makes will count how long the code is running and print it out on the display. It counts in minutes, hours and days.

The const makes it that the 4 pins: CLK = Shift Clock MOSI = Master Out Slave Out MISO = Master In Slave Out SS = Slave Select will give a value that is read-only.

const int SPICLK  = 13;
const int SPIMOSI = 11;
const int SPIMISO = 12;
const int SPISS  = 10;

Will tell to all the pins, that they should become outputs. It after that writings the value 1 (On) to Slave Select, to make a HIGH value to the digital pin.

(More about SPCR) SPCR = SPI Control Register The _BV is the bit value.~

SPE - Enables the SPI when 1
MSTR - Sets the Arduino in master mode when 1, slave mode when 0
SPR1 and SPR0 - Sets the SPI speed, 00 is fastest (4MHz) 11 is slowest (250KHz)
void SPIinit(void)
{
  pinMode (SPICLK,  OUTPUT);
  pinMode (SPIMOSI, OUTPUT);
  pinMode (SPIMISO, OUTPUT);
  pinMode (SPISS,   OUTPUT);
  digitalWrite (SPISS, 1);
  
  SPCR    =  _BV(SPE) | _BV(MSTR) | _BV(SPR1) | _BV(SPR0);
}

character ~ When SPSR(SPI Status Register) & the bit value from SPIF(SPI Interrupt Flag) is 1, it will return the received SPDR(SPI Data Register) value.

char SPI(char d) 
{  // send character over SPI
  char received = 0;
  SPDR = d;
  while(!(SPSR & _BV(SPIF)));
  received = SPDR;
  return (received);
}

When spi starts spkt it will write Slave select 0 and after that it will make it 1 again.

void SPI_startpkt (void)
{
  digitalWrite (SPISS, 0);
}

void SPI_endpkt (void)
{
  digitalWrite (SPISS, 1);
}

Name the address 0x82, that can't be changed.

static unsigned char addr = 0x82;

Makes WAIT1 be 25miliseconds, and WAIT2 be 15miliseconds.

#define WAIT1 25
#define WAIT2 15

Send to the lcd.

void send_lcd (unsigned char rnum, unsigned char len, char *s)
{  
  SPI_startpkt ();
  delayMicroseconds (WAIT1);
  SPI (addr);
  delayMicroseconds (WAIT2);
  SPI (rnum);
  delayMicroseconds (WAIT2);
  while (len--) {
    SPI (*s++);
    delayMicroseconds (WAIT2);
  }
  SPI_endpkt ();
}


void write_lcd (char *s)
{
  send_lcd (0, strlen (s), s);
}


void write_at_lcd (unsigned char x, unsigned char y, char *s)
 
{ 
  char c; 
  c = (y << 5) | (x & 0x1f);
  send_lcd (0x11, 1, &c);
  write_lcd (s);
}

void cls_lcd (void)
{ 
  char c; 
  send_lcd (0x10, 1, &c);
}

void set_var (unsigned char addr, unsigned char a, unsigned char v)
{
  SPI_startpkt ();
  delayMicroseconds (WAIT1);
  SPI (addr);
  delayMicroseconds (WAIT2);
  SPI (a);
  delayMicroseconds (WAIT2);
  SPI (v);
  delayMicroseconds (WAIT2);
  SPI_endpkt ();   
}

static unsigned char spi_servo_addr = 0x86;
static unsigned char spi_7fet_addr = 0x88;

void set_servo_var (unsigned char a, unsigned char v)
{
  set_var (spi_servo_addr, a, v);
}

void set_7fet_var (unsigned char a, unsigned char v)
{
  set_var (spi_7fet_addr, a, v);
}

void setup (void)
{
  int i;
   
  SPIinit ();  
  Serial.begin (9600);
  DDRC = 0x30;
  PORTC = 0x20;
  for (i=0;i<10;i++) {
    PINC = 0x30;
    delay (300);
  }
  cls_lcd ();
}

void loop (void) 
{
  static long nextupdate = 1000;
  static unsigned char h, m, s;
  char buf[17];
  
  if (millis () > nextupdate) {
    nextupdate += 1000;
    if (s < 59) s++;
    else {
       s = 0;
       if (m < 59) m++;
      else {
	 m = 0;
 	 if (h < 23) h++;
	 else {

h = 0; // days ++;

}

      }
    }
    sprintf (buf, "%02d:%02d:%02d", h, m, s);
    write_at_lcd (8, 1, buf);
    Serial.write (buf);
    Serial.write ("\r\n");
//    sprintf (buf, "%ld %ld", nextupdate, millis ());
//    write_at_lcd (0, 0, buf);

   // delay (100);
  }
  {
    static unsigned char olds;
   
    if (olds != s) {
      olds = s;
      set_servo_var (0x20, (s & 0xf) << 4); 
    }
  }
  
  {
    static unsigned char olds;
    
    if (olds != s) {
      static unsigned char values[4] = { 1, 4, 2, 8};
      olds = s;
     
      set_7fet_var (0x10, values [s & 0x3]); 
    }
  }

}

Useful links