chipKIT® Development Platform

Inspired by Arduino™

I2C Display issues, need some advise please.

Created Wed, 08 Jan 2014 20:12:32 +0000 by Bartje64


Bartje64

Wed, 08 Jan 2014 20:12:32 +0000

I've been developing a project with an Arduino Uno and ran out of I/O's. So I went to the Mega and all works well.......except it's physical size is too big. So I found the Uno32, plenty of I/O.

The Arduino sketch needed a bit of tweaking (still needs some more for the Uno32) but it compiled and downloaded to the Uno32 just fine.

What I cannot get to function no matter what I've tried, is the LCD display. I've verified that the jumpers are set to make A4 and A5 the I2C connection points but alas no dice. The display is a 20x4 using an I2C interface. It works with the Arduino...I'm stumped why not with the Uno32.

My code is a bit lengthy adapted from an original by Rich Visokey, I'm still learning on this (part of the fun) so in a sense still a noob. Any help or suggestions would be greatly appreciated.

[code]
/*
Main code by Richard Visokey AD7C - www.ad7c.com
 Revision 2.0 - November 6th, 2013
 */

//----------------------- Include the library codes -----------------------------------------------------------//

#include <LiquidCrystal_I2C.h>
#include <Wire.h>
#include <EEPROM.h>

//********** Chipkit or Arduino Mega 2560 ***********//
#include <Encoder.h>
//*****************************// 

//********** Arduino Uno***********//
//#include <rotary.h>
//*****************************// 

//--------------------- Declare the Pin numbers for the inputs and outputs ------------------------------------//

#define W_CLK 10   // Pin 8 - connect to AD9850 module word load clock pin (CLK)8
#define FQ_UD 9   // Pin 9 - connect to freq update pin (FQ)
#define DATA 11   // Pin 10 - connect to serial data load pin (DATA) 10
#define RESET 8  // Pin 11 - connect to reset pin (RST) 11
#define pulseHigh(pin) {digitalWrite(pin, HIGH); digitalWrite(pin, LOW); }

// --------------------- sets the pins the rotary encoder uses.  Must be interrupt pins.------------------------//

//********** Chipkit or Arduino Mega 2560 ***********// 
Encoder myEnc(2, 3);      
//***************************************************// 

//********** Arduino Uno***********//
//Rotary r = Rotary(3,2); 
//*********************************// 

//-------------------------------- Intitialize Display ----------------------------------------------------------//

LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);  // Set the LCD I2C address


//-------------------------------- Declare the variables -------------------------------------------------------//

int_fast32_t rx=5350000; // Starting frequency of VFO 
int_fast32_t rx2=1; // variable to hold the updated frequency
int_fast32_t increment = 10; // starting VFO update increment in HZ.
int_fast32_t timepassed = millis(); // int to hold the arduino miilis since startup
int_fast32_t SerialFreq = 0;
int_fast32_t Serialdata ;
int_fast32_t NewSerialdata ;


/*
160M = - 4Mhz                        
 80M = - 2Mhz
 40M = + 1.5Mhz
 30M = + 4.5Mhz
 20M = + 8.5Mhz
 17M = + 12.5Mhz
 15M = + 15.5Mhz
 12M = + 19Mhz
 10M @ 28 MHz = + 22.5Mhz
 10M @ 29 Mhz = + 23.5Mhz
 Note: Rig has + 500Khz button.
 
 BAND         DCBA
 1.5              1000****
 3.5          1100
 7.0              1101*
 10           0111**
 14               1101*
 18               1011***
 21           0111**
 24.5         1110---
 28               1011***
 28.5         1010
 29           1001
 29.5             1000**** 
 */



float  Multiplier = 1.5;
int buttonstate = 0;
int IncremAuto = 1;
int IncrementCount = 0;
int hertzPosition = 4;
int memstatus = 1;  // value to notify if memory is current or old. 0=old, 1=current.
int Freq_Changed_Count = 0;
int ChangeRx = 0;
int VFO_Limit = 0;

int Change_Rate = 0;
int Last_Stored_Pos = 0;


unsigned long lastTime = 0;
unsigned long CountTime = 800; // Count time in milliseconds

unsigned long Last_Rx_Change_Poll = 0;
unsigned long Rx_Polltime = 10; // Poll time for the writing to the serial port

unsigned long Last_Rate_Poll = 0;
unsigned long Rate_Polltime = 20; // Poll time for the rate change

String hertz = "Auto"; 
String freq; // string to hold the frequency

//**** For Kenwood ******//

String VFO = ("FA");
String Band = ("0000");
String End = (";");

byte ones,tens,hundreds,thousands,tenthousands,hundredthousands,millions ;  //Placeholders


int ForceFreq = 1;  // Change this to 0 after you upload and run a working sketch to activate the EEPROM memory.  
//YOU MUST PUT THIS BACK TO 0 AND UPLOAD THE SKETCH AGAIN AFTER STARTING FREQUENCY IS SET!

//********** Chipkit or Arduino Mega 2560 ***********// 
long oldPosition  = 0;
long newPosition = 0;
int EncoderSensitivity = 10;
//***************************************************// 


//------------------------------- Initialize the I/O's -------------------------------------------------------//

void setup() {

  //********** Arduino Uno ***********// 
  //PCICR |= (1 << PCIE2);
  //PCMSK2 |= (1 << PCINT18) | (1 << PCINT19);
  //sei();
  //**********************************//  

  lcd.begin(20, 4);
  lcd.setCursor(0,0);
  lcd.print("Freq.");
  lcd.setCursor(0,2);
  lcd.print("Mode");
  lcd.setCursor(0,3);
  lcd.print("Stp.");
  lcd.setCursor(10,3);
  lcd.print("Bnd.");
  lcd.setCursor(17,3);
  lcd.print("Mtr");
  lcd.setCursor(hertzPosition,3);    
  lcd.print(hertz);

  pinMode(FQ_UD, OUTPUT);
  pinMode(W_CLK, OUTPUT);
  pinMode(DATA, OUTPUT);
  pinMode(RESET, OUTPUT); 
  pulseHigh(RESET);
  pulseHigh(W_CLK);
  pulseHigh(FQ_UD);  // this pulse enables serial mode on the AD9850 - Datasheet page 12.

  pinMode(5,INPUT); // Connect to a button that goes to GND on push


  Serial.begin(9600);

  //------------------------Read the values stored in the EEprom --------------------------------------------------// 
  if (ForceFreq == 0) {
    freq = String(EEPROM.read(0))+String(EEPROM.read(1))+String(EEPROM.read(2))+String(EEPROM.read(3))+String(EEPROM.read(4))+String(EEPROM.read(5))+String(EEPROM.read(6));
    rx = freq.toInt();
  }
};

//-------------------------------------- Program Section ---------------------------------------------------------// 

void loop() {

  //*************** Calculate the rate of change frm the encoder position ************************//

  if ((millis() - Last_Rate_Poll  >= Rate_Polltime)){   // wait for Poll time milliseconds
    Last_Rate_Poll = millis();
    Change_Rate = ((newPosition - Last_Stored_Pos)/1);
    Last_Stored_Pos = newPosition;

  }

  //*************** Write to the Serial Port if the frequency is being changed by the encoder ************************//

  if ((millis() - Last_Rx_Change_Poll  >= Rx_Polltime)&&(ChangeRx)){   // wait for Poll time milliseconds
    Last_Rx_Change_Poll = millis();
    SerialFreq =(rx+(Multiplier*1000000));  
    String Send = (VFO+Band+SerialFreq+End);   
    Serial.println(Send);
    //Serial.println(increment);
    //Serial.println abs(Change_Rate);
    ChangeRx = 0;    
  }

  if (Multiplier == 1.5){
    lcd.setCursor(15,3);
    lcd.print ("40");
    lcd.setCursor(1,1);
  }

  if (rx != rx2){    
    showFreq();
    sendFrequency(rx);
    rx2 = rx;
  }

  //****************** Read the Button State for changing the increments ***************

  buttonstate = digitalRead(5);
  if(buttonstate == HIGH) {
    IncremAuto = 0;
    setincrement();        
  };

  // ****************** Write the frequency to memory if not stored and 1 second has passed since the last frequency change.**********
  //******************* If in Auto mode default the increment back to 10 after 1 second has passed.********

  if(memstatus == 0){   
    if(timepassed+1000 < millis()){
      storeMEM();
      if(IncremAuto == 1){
        increment = 10;
        Freq_Changed_Count = 0;
      }
    }
  };
  if (IncremAuto == 1){ 
    Auto();
  }; 

  //******************* Look for movement on the encoder.************************

  //********** Chipkit or Arduino Mega 2560 ***********//

  newPosition = myEnc.read();
  if (newPosition != oldPosition) { 

    if (newPosition >= (oldPosition + EncoderSensitivity)){
      //Serial.println("ccw");
      ChangeRx = 1; 
      rx=rx-increment;
      oldPosition = newPosition;
    }
    if (newPosition <= (oldPosition - EncoderSensitivity)){
      //Serial.println("cw");
      ChangeRx = 1;
      rx=rx+increment;
      oldPosition = newPosition;
    }
  }
  //****************************************************//

  //********** Arduino Uno ***********//

  //ISR(PCINT2_vect)

  // unsigned char result = r.process(); 
  //if (result) {
  //ChangeRx = 1;    
  //if (result == DIR_CW){
  // rx=rx+increment; 
  //;
  //}          
  // else {
  //  rx=rx-increment;     
  // }
  //}

  //**********************************//

  //****** UPPER AND LOWER VFO LIMIT ******//     
  if ((rx >=6150000) || (rx <=5350000)){    
    VFO_Limit = 1;
  }
  else{
    VFO_Limit = 0;
  } 
  if ((rx >=6150001) || (rx <=5349999)){
    rx=rx2;
  }
}

// ********************* frequency calc from datasheet page 8 = <sys clock> * <frequency tuning word>/2^32 *********** //

void sendFrequency(double frequency) { 

  int32_t freq = frequency * 4294967295/124999550;  // note 125 MHz clock on 9850.  You can make 'slight' tuning variations here by adjusting the clock frequency.
  for (int b=0; b<4; b++, freq>>=8) {
    tfr_byte(freq & 0xFF);
  }
  tfr_byte(0x000);   // Final control byte, all 0 for 9850 chip
  pulseHigh(FQ_UD);  // Done!  Should see output
};

// ************** transfers a byte, a bit at a time, LSB first to the 9850 via serial DATA line **************

void tfr_byte(byte data){

  for (int i=0; i<8; i++, data>>=1) {
    digitalWrite(DATA, data & 0x01);
    pulseHigh(W_CLK);   //after each bit sent, CLK is pulsed high
  }
};

//void serialEvent(){

//*************** Read the Serial Port if the frequency is being changed by the program ************************//

//if (Serial.available() > 0){
//********** Arduino ***********//
//Serialdata = Serial.parseInt();

//********** Chipkit ***********//
//Serialdata = Serial.read();

//if ((Serialdata > 1)&&(!NewData)){
// NewSerialdata = Serialdata;
//NewData = 1;
//}
//NewData = 0;
//rx = (NewSerialdata - (Multiplier*1000000));
//}
//};

//-------------------------------------- Manual Step Increments for frequency change ----------------------------//

void setincrement(){

  IncrementCount = IncrementCount +1; 

  if (IncrementCount == 1){
    IncremAuto = 0; 
    increment = 10;
    hertz = "10Hz"; 
    hertzPosition=4;
  }
  else if (IncrementCount == 2){
    IncremAuto = 0; 
    increment = 100;
    hertz = "100Hz"; 
    hertzPosition=4;
  }  
  else if (IncrementCount == 3){
    IncremAuto = 0;
    increment = 250;  
    hertz = "250Hz"; 
    hertzPosition=4;
  } 
  else if (IncrementCount == 4){
    IncremAuto = 0;
    increment = 500; 
    hertz="500Hz"; 
    hertzPosition=4;
  }
  else if (IncrementCount == 5){
    IncremAuto = 0;
    increment = 1000;
    hertz="1Khz "; 
    hertzPosition=4;
  }
  else if (IncrementCount == 6){
    IncremAuto = 0;
    increment = 2000; 
    hertz="2Khz "; 
    hertzPosition=4;
  }  
  else if (IncrementCount == 7){
    IncremAuto = 1;
    increment = 10;
    hertz="Auto";
    hertzPosition=4;
    IncrementCount = 0;
  } 
  lcd.setCursor(hertzPosition,3); 
  lcd.print(hertz); 
  delay(500); // Adjust this delay to speed up/slow down the button menu scroll speed.
};

//-------------------------------------- Step Increments for frequency change when in Auto mode --------------------------------------------------------// 
void Auto(){

  //********* Maps the change rate to increment rate********//
  increment = (10*(map(abs(Change_Rate), 20,40, 10,150))); 
  //********* Linits the increment rate********//
  increment =constrain(increment, 10,1500);                    
  //Serial.println(increment);

};

//-------------------------------------- Show the frequency on the display ---------------------------------------------------------/

void showFreq(){

  Freq_Changed_Count = Freq_Changed_Count +1;

  int_fast32_t rxprnt = (rx+(Multiplier*1000000)); 
  millions = int(rxprnt/1000000);
  hundredthousands = ((rxprnt/100000)%10);
  tenthousands = ((rxprnt/10000)%10);
  thousands = ((rxprnt/1000)%10);
  hundreds = ((rxprnt/100)%10);
  tens = ((rxprnt/10)%10);
  ones = ((rxprnt/1)%10);
  lcd.setCursor(4,0);
  //lcd.print("                ");
  if (millions > 7){
    lcd.setCursor(6,0);
  }
  else{
    lcd.setCursor(7,0);
  }
  lcd.print (millions);
  lcd.print(".");
  lcd.print(hundredthousands);
  lcd.print(tenthousands);
  lcd.print(thousands);
  lcd.print(".");
  lcd.print(hundreds);
  lcd.print(tens);
  
  //********do not need "ones" displayed on the lcd ************//
  //lcd.print(ones); 
  //************************************************************//
  
  lcd.print(" Mhz ");
  timepassed = millis();
  memstatus = 0; // Trigger memory write 
};

void storeMEM(){

  //Write each frequency section to a EPROM slot.  Yes, it's cheating but it works!
  EEPROM.write(0,int(rx/1000000));
  EEPROM.write(1,((rx/100000)%10));
  EEPROM.write(2,((rx/10000)%10));
  EEPROM.write(3,((rx/1000)%10));
  EEPROM.write(4,((rx/100)%10));       
  EEPROM.write(5,((rx/10)%10));
  EEPROM.write(6,((rx/1)%10));   
  memstatus = 1;  // Let program know memory has been written
};

[/code]


mikes

Wed, 08 Jan 2014 21:49:42 +0000

Do you have pull up resistors on the I2C lines? Arduino uses some internal ones on the processor. For Chipkit you need to add them yourself about 2k is a good size.


Bartje64

Wed, 08 Jan 2014 22:36:39 +0000

Pullup resistors? This is the first I heard of that.

Where...from each pin to ground? or 3.3v to each via resistor?

I guess to ground would be pull-down...

Bart


mikes

Wed, 08 Jan 2014 23:12:12 +0000

I²C requires pull-up resistors on its clock (SCL) and data line (SDA) because the pins on the chips are of open-collector design. This means that a chip can only pull the lines low, otherwise they float up to VDD. In I²C, pulling the line to ground indicates a logical zero while letting it float to VDD is a logical one. As a channel access method, this allows one node to determine if another is transmitting by asserting an output, letting the external pull-up resistor pull the line to logic 1 level, and monitoring the line state. If a second node pulls the line to zero, then the first node can detect that the other is transmitting.

You are correct it is a resistor between the signal line and 3.3 or 5 volts depending on the design.


Bartje64

Thu, 09 Jan 2014 01:15:24 +0000

Well I'll be.....it works!

I re-read the pdf doc (Reference manual) and it does state that resistors are needed (just not what value).Duh..... next time I have to pay more attention...

Thanks for all the help guys! Bart