Difference between revisions of "Blog 20"

From BitWizard WIKI
Jump to: navigation, search
(!BETA!Understanding the I2C example code)
(!BETA!Understanding the I2C example code)
Line 76: Line 76:
  
 
The 0x82 is in this example bit shifted(>>) to the right by one. Bit shifting in this example let's all the bits go to the right. So what will happen:
 
The 0x82 is in this example bit shifted(>>) to the right by one. Bit shifting in this example let's all the bits go to the right. So what will happen:
0x82 (Hex) = 1000 0010  
+
0x82 (Hex) = 1000 0010  
1000 010 >> 1 = 01000001 = 0x41 (Hex)
+
1000 010 >> 1 = 01000001 = 0x41 (Hex)
( As you can see all the 1's are going to the right )
+
( As you can see all the 1 bits are going to the right )
  
 
In this example Using bit shifting is an easy technique, so that you don't have to calculate what the I2c address value is.  
 
In this example Using bit shifting is an easy technique, so that you don't have to calculate what the I2c address value is.  
  
(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.  
+
(cls = clear screen) 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)
 
  void lcd_cls (void)
 
  {
 
  {
Line 91: Line 91:
 
  }
 
  }
  
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.  
+
char *str, will make a pointer to str. For new people like me that can be confusing so it is recommended for now to see it as: 'char str[]'.
 +
He again start transmitting to the address to register 0x0 and with the value given in the str.  
 +
 
 
  void lcd_print (char *str)
 
  void lcd_print (char *str)
 
  {
 
  {
Line 100: Line 102:
 
  }
 
  }
  
This will make contact to int x and int y. It will start transmitting to the address and talk to register 0x11.  
+
This will put the print text on the wanted position on the display. It says the x and y position from the printed information.  
 +
It will start transmitting to the address and talk to register 0x11, which refreshes the page.  
 
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.  
 
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.  
 
After that it will stop transmitting.  

Revision as of 15:04, 1 December 2015

!BETA!Understanding the I2C example code

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

I would recommend if you are new to arduino to search stuff up you are unfamiliar with.
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 how long the code is running. It counts in seconds, minutes and hours.

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> 

Make 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 by one. Bit shifting in this example let's all the bits go to the right. So what will happen:

0x82 (Hex) = 1000 0010 
1000 010 >> 1 = 01000001 = 0x41 (Hex)

( As you can see all the 1 bits are going to the right )

In this example Using bit shifting is an easy technique, so that you don't have to calculate what the I2c address value is.

(cls = clear screen) 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
}

char *str, will make a pointer to str. For new people like me that can be confusing so it is recommended for now to see it as: 'char str[]'. 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 put the print text on the wanted position on the display. It says the x and y position from the printed information. It will start transmitting to the address and talk to register 0x11, which refreshes the page. 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 seconds, minutes and hours. ( Also does days if you remove the comments(//).

The const makes it that the 4 pins:

  • SPICLK = SPI Shift Clock
  • SPIMOSI = SPI Master Out Slave Out
  • SPIMISO = SPI Master In Slave Out
  • SPISS = SPI 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;

The pinMode lines will make all the pins outputs. After that it writes the value 1(HIGH) to the Slave Select pin.

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

  • SPE(SPI Enable) - Enables the SPI when 1
  • MSTR(Master mode) - Sets the Arduino in master mode when 1, slave mode when 0
  • SPR1 and SPR0(Speed per round) - 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 ();
}

Send to lcd string length

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

Unsigned char is an unsigned datatype, works the same as byte. Value y gets bit shifted 5 steps to the left. ( More about bit shifting you can read above at the I2C part.)

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);
}

(cls = Clear Screen )

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

Direction to set_var, where address, register and value can be given. It has several waits, that direct to the times given before at #WAIT1 and #WAIT2.

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 ();   
}

Make clear what the addresses are from the servo and 7FETs.

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);
}

DDRC - The Port C Data Direction Register - read/write PORTC - The Port C Data Register - read/write PINC - The Port C Input Pins Register - read only

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 ();
}

static long makes that the number can't be negative. Millis = Returns the number of milliseconds since the Arduino board began running the current program. So, if it is more than value next update 1000 milliseconds(1 second) it wil run the script. In the script it will count at s ( seconds ) 1. (s+) If S is higher than 59 it will set s back to 0. And will count 1 at the (m)minutes section. This works the same for the minutes section when it is geting above 59 it will count 1 to (h)hours.

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 ++;
        }
      }
    }

Here it will print out the given value from the if statement above. (%02d) And will print it out in 2 numbers on the display in decimals. Gives the values to open writing to display. And puts with buf the information in it from the arrays.

    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);
  }

This is for talking to the servo and the 7FETs. Register 0x20, with value s an reference 0xf gets bit shifted 4 times to the left.

  {
    static unsigned char olds;
   
    if (olds != s) {
      olds = s;
      set_servo_var (0x20, (s & 0xf) << 4); 
    }
  }
  

Makes a string, of four values. For values 1, 4, 2 and 8. Olds will than read what the latest values is that is given to s. At 7FETs address the register 10 will set the given outputs at value to zero.

  {
    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