• You can now help support WorldwideDX when you shop on Amazon at no additional cost to you! Simply follow this Shop on Amazon link first and a portion of any purchase is sent to WorldwideDX to help with site costs.

CBduino Lite V1_0

SLR_65

Active Member
Dec 27, 2014
104
16
28
CBduino Lite V1_0

This version of CBduino has the lcd display routines removed so you'll need a radio with a frequency counter (internal or external).

It simply reads a 10K pot and adjusts the PLL settings from the lowest to the highest.

This isn't radio specific, any radio with a 8719 will do, just disconnect the channel selector from the PLL and connect the PLL to the output of the level shifter.

This version is designed to run on the Arduino Nano, though it also runs on the Uno, possibly others but they are untested.

I'll be working on interfacing to the channel selector next.

Enjoy!
 

Attachments

  • CBduino Lite V1_0.pdf
    42.7 KB · Views: 33

Can you simplify the check_what_channel function by replacing it with:

void check_what_channel() {
pot_val=analogRead(pot_pin); // analog reading the 10K pot
channel = map(pot_val, 0, 1023, 1, 128);
}

Note, there was an error in the map function that may or may not have been fixed in the core arduino code, but I don't think it would matter in this use either way.
 
See if the code below works. It takes significantly less program space:

Code:
int pot_pin = 3; // a 10K pot center lug is hooked to analog input 3
int pot_val = 0; // holds the value read from the pot, will be 0 to 1023
int channel = 1; // holds PLL channel the pot value represents
int pll_lowest_divisor = 63; // lowest pll setting minus one, the 8719 lowest divisor is 64
byte output_to_pll; // holds the byte that will be written to the PLL

void setup() {
  for (int i=0; i <= 7; i++){
    pinMode(i, OUTPUT); // sets pin ports 0 through 6 as an output
  }
}

void loop() {
  check_what_channel(); // this function reads the pot and returns what channel it represents
  generate_pll_divisor(); // this function generates the pll divisor settings for the channel selected
}

//****Functions****//

void check_what_channel() {
  pot_val=analogRead(pot_pin); // analog reading the 10K pot
  channel = map(pot_val, 0, 1023, 1, 128);
}

void generate_pll_divisor() {
  output_to_pll = pll_lowest_divisor + channel;
  for (int i=0; i <= 7; i++){
    if (bitRead(output_to_pll, i) == 0) digitalWrite(i, LOW); 
    else digitalWrite(i, HIGH);
  }
}
 
For the Console V is was working with, I used an array to hold the values of the 40 channels, and another one for the BSD digits for the channel display. I had already started working on Arduino control for another radio (or two) and decided that arrays can make life very easy, once you have the initial data loaded. So here's what I currently have for the MB8719 as it's set up in the Cobra 2000:
----
// Array for MB8719 standard 40 channels
//
// Individual elements are set in PLL chip pin order, pins 10,11,12,13,14,15, and 16. This corresponds
// to the I/O pins 23,25,27,29,31,33,and 35 from the Arduino Mega that I've chosen here.
//
// To expand the number of channels, add the seven bit values to the array
// and change the "[40]" to the new number of channels.
//
// The current arrangement is for the standard FCC channels in slots 0 through 39,
// including the "A" channel skips and the "out of order" channels 23,24, and 25.
//
//

int PLL[7]={23,25,27,29,31,33,35};

byte CHNL[40] [7]={{1,0,0,1,1,1,1},{1,0,1,0,0,0,0},{1,0,1,0,0,0,1},{1,0,1,0,0,1,1},{1,0,1,0,1,0,0},
{1,0,1,0,1,0,1},{1,0,1,0,1,1,0},{1,0,1,1,0,0,0},{1,0,1,1,0,0,1},{1,0,1,1,0,1,0},
{1,0,1,1,0,1,1},{1,0,1,1,1,0,1},{1,0,1,1,1,1,0},{1,0,1,1,1,1,1},{1,1,0,0,0,0,0},
{1,1,0,0,0,1,0},{1,1,0,0,0,1,1},{1,1,0,0,1,0,0},{1,1,0,0,1,0,1},{1,1,0,0,1,1,1},
{1,1,0,1,0,0,0},{1,1,0,1,0,0,1},{1,1,0,1,1,0,0},{1,1,0,1,0,1,0},{1,1,0,1,0,1,1},
{1,1,0,1,1,0,1},{1,1,0,1,1,1,0},{1,1,0,1,1,1,1},{1,1,1,0,0,0,0},{1,1,1,0,0,0,1},
{1,1,1,0,0,1,0},{1,1,1,0,0,1,1},{1,1,1,0,1,0,0},{1,1,1,0,1,0,1},{1,1,1,0,1,1,0},
{1,1,1,0,1,1,1},{1,1,1,1,0,0,0},{1,1,1,1,0,0,1},{1,1,1,1,0,1,0},{1,1,1,1,0,1,1}};

// To write array position 22 (channel 23) out to the PLL you could do something like this:

for(int a=0; a < 7; a++){
digitalWrite(PLL[a], CHNL{[22] [a]);}

// Of course, to have more than one channel you would use a variable in place of the number 22.
----

This is just an example. You could easily have a 50 or 60 "channel" array, or several arrays that you choose from based on "band", or any other number of permutations.
 
Hi C2,

Attached is a PDF with the parts, hookup info and a couple pics.

The level shifter has 500K pull downs in it, 5-10k is usually used, the 959 uses 1k, but so far it's been stable just using the internal ones in the level shifter. I've only been testing using an a/c supply and not much transmitting though, so we may have to use external pull downs in some radios if problems creep up, for now I'm keeping the parts list down unless practice shows we need them.

The channel lookup could be done better, but I envisioned this as base code others may want to build on and in the method I used it's easy to re-order the channels to accommodate the CB channels that skip and 23/24/25 odd arrangement.

A more efficient routine that accommodates those odd channels is something I eventually want to work on as more programming space means more bells and whistles we can put in.

/Steve
 

Attachments

  • CBduino Lite V1 Hardware.pdf
    229.5 KB · Views: 35
Hi TM86, I'll take a look...at first glance we could:

Use the channel selector, once all forty slots in a particular band have been ran through then change a band flag in the eeprom.

Have a forty slot array for each band, switch arrays based on the band flag.

Though the PLL is capable of 128 channels just doing three bands of forty channels each would match up better.

The Arduino eeprom is rated at 100,000 read write cycles but maybe it would be prudent to keep track of the cycles and switch to another byte every 80,000 or so?

I like the massive amount of ports available on the Mega, but have you ran into the bug where it won't upload your code? The problem is in the code being uploaded, there are several identified things that will hang it, though some unidentifieds will too, and it's darn annoying! I've ran into it a couple times. Saving your work and testing upload often helps and then if a problem shows up it isn't so hard to run down, but it's darn annoying so I've been opting for Unos, Leonardos and Nanos with I2C port expanders.
 
Use the channel selector, once all forty slots in a particular band have been ran through then change a band flag in the eeprom.

Have a forty slot array for each band, switch arrays based on the band flag.

Whatever you want to do with it, or not do with it. More or less it's the MB8719 truth chart of the FCC 40 channels in an array format. Since I haven't implemented anything in hardware just yet, I haven't checked that it works as advertised.

The Arduino eeprom is rated at 100,000 read write cycles but maybe it would be prudent to keep track of the cycles and switch to another byte every 80,000 or so?

That could work. Of course, you'll need to reserve a byte to keep track of where that byte you just switched to is. Kind of like an inode in a unix filesystem. And if there's over 80,000 alternate locations, well, we're in the neighborhood of 6.4 million writes. I don't know how often you're planning on writing out, but that seems like it should last for a while. A week or two at least.

I like the massive amount of ports available on the Mega, but have you ran into the bug where it won't upload your code?

Not yet, though now I know to look out for it so I probably will. Ignorance was bliss.

The problem is in the code being uploaded, there are several identified things that will hang it, though some unidentifieds will too, and it's darn annoying! I've ran into it a couple times. Saving your work and testing upload often helps and then if a problem shows up it isn't so hard to run down, but it's darn annoying so I've been opting for Unos, Leonardos and Nanos with I2C port expanders.

I used the Mega because it was available locally and there was lots of pins on it. As I said before, I haven't had any problems just yet. You say you have, and I've no reason to doubt you on that.

Now I have to go look up I2C port expanders. I should probably be careful, I might learn something.
 
I get by with a little help from my friends...

This version is significantly smaller in program size, though the variable storage has increased.

It was known in earlier versions that using a loop to handle the channel lookup would be quicker, it didn't allow
for channel numbering that accommodated the extra channels
and the odd arrange of 23, 24 and 25 though.

A thread poster on the WWDX forum suggested using the loop to assign channel numbers that are used as an index to a data array containing the PLL settings, by doing so we can
use the quick loop channel sort and still accommodate reordering the channels...pretty slick!
 

Attachments

  • CBduinoLiteV11.pdf
    33.3 KB · Views: 32
A thread poster on the WWDX forum suggested using the loop to assign channel numbers that are used as an index to a data array containing the PLL settings, by doing so we can
use the quick loop channel sort and still accommodate reordering the channels...pretty slick!

Another advantage. If you're really happy with the how this code works, but would like to use it on another PLL chip it's very simple to port it over.

Say you had an 8 bit PLL capable of 255 channels. I think three total changes in the code itself would do the trick.

First, the line "int output_to_pll[7] = {8,7,6,5,4,3,2};" becomes "int output_to_pll[8] = {8,7,6,5,4,3,2,<new pin>};".

The array definition "byte CHNL[128] [7]" becomes "byte CHNL[255] [8]", and the line "for(int a=0; a < 7; a++)" becomes "for(int a=0; a < 8; a++)".

After that, it's just a matter of updating the array data for the new PLL.

Got a PLL with 10 programming lines that can do ~399 channels? I think you can figure out what would need to be done.

Late edit: Four changes to the code, "channel = map(pot_val, 0, 1023, 0, 127);" would become, I think, "channel = map(pot_val, 0, 1023, 0, 255);".

Need to read the whole file before commenting. :confused:
 
Yep, I LIKE this version of the sketch!

It's using up some variable storage though. Currently that's not a big deal, but if you're going to add in 300+ channels it could be. 8-D I think there's a way to store an array in program storage, just gotta take the time to dig that up.
 
Here's where I'm at:

Code:
// Array for MB8719 standard 40 channels
//
// Individual elements are set in PLL chip pin order, pins 10,11,12,13,14,15, and 16. This corresponds
// to the I/O pins 23,25,27,29,31,33,and 35 from the Arduino Mega that I've chosen here.
//
// To expand the number of channels, add the seven bit values to the array
// and change the "[40]" to the new number of channels.
//
// The current arrangement is for the standard FCC channels in slots 0 through 39,
// including the "A" channel skips and the out of order channels 23,24, and 25.
//
//

int PLL[7]={23,25,27,29,31,33,35};
int CHSEL[7]={24,26,28,30,32,34,36};

// The ONES and TENS arrays control the LED channel display.  Pins are arranged in ascending
// order a,b,c,d,e,f,g, such that Arduino pin 37 would connect to segment "a" of the ones digit seven
// segment display.

int ONES[7]={37,39,41,43,45,47,49};
int TENS[7]={38,40,42,44,46,48,50};

// The values here are for the seven segment LED display, and display the numbers 0 through 9, the
// letters A, b, c, d, E, and F, as well as a blanking character.  If you ever see the letters,
// you know something's probably wrong or your new code works.

byte SVNSEG[16] [7]={{1,1,1,1,1,1,0},{0,1,1,0,0,0,0},{1,1,0,1,1,0,1},{1,1,1,1,0,0,1},{0,1,1,0,0,1,1},{1,0,1,1,0,1,1},
{1,0,1,1,1,1,1},{1,1,1,0,0,0,0},{1,1,1,1,1,1,1},{1,1,1,1,0,1,1},{1,1,1,0,1,1,1},
{0,0,1,1,1,1,1},{0,0,0,1,1,0,1},{0,1,1,1,1,0,1},{1,0,0,1,1,1,1},{1,0,0,0,1,1,1},
{0,0,0,0,0,0,0}};

byte CHNL[40] [7]={{1,0,0,1,1,1,1},{1,0,1,0,0,0,0},{1,0,1,0,0,0,1},{1,0,1,0,0,1,1},{1,0,1,0,1,0,0},
{1,0,1,0,1,0,1},{1,0,1,0,1,1,0},{1,0,1,1,0,0,0},{1,0,1,1,0,0,1},{1,0,1,1,0,1,0},
{1,0,1,1,0,1,1},{1,0,1,1,1,0,1},{1,0,1,1,1,1,0},{1,0,1,1,1,1,1},{1,1,0,0,0,0,0},
{1,1,0,0,0,1,0},{1,1,0,0,0,1,1},{1,1,0,0,1,0,0},{1,1,0,0,1,0,1},{1,1,0,0,1,1,1},
{1,1,0,1,0,0,0},{1,1,0,1,0,0,1},{1,1,0,1,1,0,0},{1,1,0,1,0,1,0},{1,1,0,1,0,1,1},
{1,1,0,1,1,0,1},{1,1,0,1,1,1,0},{1,1,0,1,1,1,1},{1,1,1,0,0,0,0},{1,1,1,0,0,0,1},
{1,1,1,0,0,1,0},{1,1,1,0,0,1,1},{1,1,1,0,1,0,0},{1,1,1,0,1,0,1},{1,1,1,0,1,1,0},
{1,1,1,0,1,1,1},{1,1,1,1,0,0,0},{1,1,1,1,0,0,1},{1,1,1,1,0,1,0},{1,1,1,1,0,1,1}};

void setup()
{
  // "Ones" display
  for(int a=0;a<7;a++){
  pinMode(ONES[a], OUTPUT);}

  // "Tens" display
  for(int a=0;a<7;a++){
  pinMode(TENS[a], OUTPUT);}

  // PLL programming
  for(int a=0;a < 7;a++){
  pinMode(PLL[a], OUTPUT);}

  // Channel select reading
  for(int a=0;a < 7;a++){
  pinMode(CHSEL[a], INPUT);}

}

void loop ()
{
  for(int a=0;a < 7; a++){
  digitalRead(CHSEL[a]);}

  for(int CH=0; CH < 40; CH++){
  for(int CHBIT=0; CHBIT < 7; CHBIT++){
  int TEST1=CHNL[CH] [CHBIT];
  int TEST2=CHSEL[CHBIT];
  if(TEST1 == TEST2){
  READCH=CH
  }
  }
  }

  if (READCH < CURRCH){
  if (CURRCH < 40){
  CURRCH++;
  }else{
  CURRCH=0;
  }
  }
  if (READCH > CURRCH){
  if ( CURRCH > 0){
  CURRCH--;
  }else{
  CURRCH=39;
  }
  }

  int CHP1=CURRCH + 1
  int ONESchannel=CHP1 % 10;
  int TENSchannel=CHP1 / 10;
  if (TENSchannel == 0){
  TENSchannel=16;}
  for(int SVB=0;SVB < 7; SVB++){
  digitalWrite(ONES[SVB], SVNSEG[ONESchannel][SVB]);
  digitalWrite(TENS[SVB], SVNSEG[TENSchannel][SVB]);}
  for(int SCHB=0;SCHB < 7; SCHB++){
  digitalWrite(PLL[SCHB], CHNL[CURRCH][SCHB]);}
}

I haven't tested this on hardware. This code may cause any given radio to fry the PLL, blow up the finals, or possibly open a portal to hell.
 
Have you thought about OLED?

One of the guys on the Yahoo group has found a .96 OLED, about $10 off fleaBay, fits nicely into a CB channel display window.

The library takes up about a third of the program space, but it could probably be streamlined and your sketch is small anyway, no need to leave program space empty when you could use it for a pretty display!
 

Attachments

  • CB OLED.jpg
    CB OLED.jpg
    152.6 KB · Views: 25

dxChat
Help Users
  • No one is chatting at the moment.