Proper use of portD

Hello,
I am new to Arduino having used Xilinx FPGA for most of my computer aided circuit design.

I want to use the PortD = 0bxxxxxxxx command to select pins to run a 3 digit LED display. I will use three other pins to multiplex the display (at least that’s my plan). I am attempting to make a 3 digit readout that will ultimately serve as a counts per second output for a geiger counter I designed and built. I will attempt to get the 3 digit display working on an analog input value first so I can verify my code and so I can make numbers increment with a potentiometer (sounds like fun). Then i’ll write the code to another chip and mount it to a PCB inside my geiger counter (with relevant clock and other discreet parts).

If I use DDRB = B11111111 or pinMode command to set portD as all output, will that block the Tx/Rx port? Isn’t that the port used to program the chip? If I write this code and upload to the Arduino, will I then not be able to rewrite the chip anymore? I considered using a delay(10000) in the setup() section of the code to give a 10 second buffer before the port was taken over so I could modify my code or erase the chip if I needed to. I also thought about just using a 7447 to drive the display, use port B to send the 4 bit value, and use pins on port D to handle the multiplexing. Can someone please help me?

bigscot:
Hello,
I am new to Arduino having used Xilinx FPGA for most of my computer aided circuit design.

Welcome!

I want to use the PortD = 0bxxxxxxxx command to select pins to run a 3 digit LED display. I will use three other pins to multiplex the display (at least that’s my plan). I am attempting to make a 3 digit readout that will ultimately serve as a counts per second output for a geiger counter I designed and built. I will attempt to get the 3 digit display working on an analog input value first so I can verify my code and so I can make numbers increment with a potentiometer (sounds like fun). Then i’ll write the code to another chip and mount it to a PCB inside my geiger counter (with relevant clock and other discreet parts).

Sounds like a good approach.

If I use DDRB = B11111111 or pinMode command to set portD as all output, will that block the Tx/Rx port? Isn’t that the port used to program the chip? If I write this code and upload to the Arduino, will I then not be able to rewrite the chip anymore?

It will prevent use of the serial port only while your code is running. The programming process starts with putting the chip into reset state, which causes all registers to be reset to their initial values as defined in the datasheet. So reprogramming the chip will be no problem.

I considered using a delay(10000) in the setup() section of the code to give a 10 second buffer before the port was taken over so I could modify my code or erase the chip if I needed to. I also thought about just using a 7447 to drive the display, use port B to send the 4 bit value, and use pins on port D to handle the multiplexing. Can someone please help me?

Not necessary as noted above. No reason the 7447 approach wouldn’t work. I did a similar project and ended up using parts of two ports for the segment drivers. Makes the coding slightly more trouble but works fine. Be sure to use a transistor on the pins that are the digit drivers, as a pin probably cannot source or sink enough current for an entire digit (20mA limit).

My circuit attached FWIW.

Thank you so much for your help, I really appreciate it. I will post my design once it's up and running.

I am going to go ahead with this project. I think I will attempt to use a 3 digit display, and a pushbutton to select from counts per second, counts per minute, counts per 10 minute (for background rad check), and maybe sieverts or millirems too. I have designed the geiger counter to output to a 555 timer. This is because the pulses are so short from the tube. I will have a random timed square wave that I need to synchronize. A string of flip flops would be an easy way to do this, but I am going to use arduino only. Anyone have a suggestion?

bigscot: I have designed the geiger counter to output to a 555 timer. This is because the pulses are so short from the tube.

How short are they? (I'm ignorant of Geiger tube characteristics.)

I will have a random timed square wave that I need to synchronize.

Synchronize to what? Don't the pulses just need to be counted? Or their period measured?

The pulses from the geiger counter can be pretty short. The tube diameter is about 12 mm, and the time of pulse is the time it takes a ‘hot’ particle to ionize the inert gas within the tube. I think this can happen in less than a microsecond, but I haven’t hooked the pulse stream to my USB oscilloscope for fear it may damage it (the geiger counter pulse comes from a 495V/5V voltage divider). Im sure it would be fine, but I included a 555 timer in one-shot mode as a sort of buffer. The tube has a min response of ~50 microseconds because the gas needs time to recover after ionization, so I set the pulsewidth out of the 555 with a 1K resistor and .047 uF cap for about 500 microseconds. I figure I don’t need to be around anything that has a higher radiation count. This square wave output from the 555 with then be of constant on time pulsewidth, but the off time will vary. The counter as measured with a circuit I built with my FPGA board will hit about 800 counts per second.

here is the code as of this moment:

// geiger counter display
// By Scott Damiani
// July 26, 2013
// 

// this is the analog input pin set as "read-only"
// meaning the pin assignment to variable "analogpin" won't change

const int analogPin = A0; // set analog input pin as A0 with analogRead
const int maxvalue = 999;


void setup() // run these once
{
  DDRD = B11111111; // set port D pins as digital outputs 7:0
  DDRB = B111111;  // set port B pins as digital outputs 13:8

  // not needed with DDRB  pinMode(8, OUTPUT);
  //                        pinMode(9, OUTPUT);
  //                        pinMode(10, OUTPUT); // set 8, 9, and 10 as outputs

  int num3 = 0;
  int num2 = 0;
  int num1 = 0;
  int digitSelect = 1;
  // this cannot go here for some reason -->  int num = 1;
}


void loop () // the main program

{
  int lastsquarestate = 0;
  int decaycounts = 0;
  int displayvalue = 0;

  // read the pot or input value

  int squarestate = digitalRead(analogPin); // squarestate gets 0 or 1
 
  if (squarestate !=lastsquarestate) //check for state change
  {
  if (squarestate == HIGH) //if high then increment counter
  {
  decaycounts++;}}
  int time = millis(); //set current run time milliseconds as time
  
  if (time%1000 == 0) //at one second, displayvalue gets decaycountys, then decaycounts is reset
  {
  displayvalue = decaycounts;
  decaycounts = 0;
  }

  // distribute the result to displayable characters 3 chars = [0,999]
  
  // seperate the values for the seperate segments

  int num3 = (displayvalue/100);  // seperates the 100's digit and set it to num3 active on pin 10

    int num2 = ((displayvalue/10)-(num3*10));  // seperates the 10's digit and set it to num2 active on pin 9

  int num1 = ((displayvalue)-(num2*10)-(num3*100));   // seperates the 1's digit and set it to num1 active on pin 8



  for (int digitSelect = 1; digitSelect<4; digitSelect++) // selects a number to set active on display

  {
    // delay(1);  // this line eliminates bleed/blur from the other numbers but makes the MSB go crazy

    int num = 1;  // this won't work above

    if (digitSelect == 1) {
      num = num1; 
      PORTB = B000110;
    } // sends LOW to pin 8 and biases LED#1 power switching transistor MSB

    if (digitSelect == 2) {
      num = num2; 
      PORTB = B000011;
    } // sends LOW to pin 9 and biases LED#2 power switching transistor

    if (digitSelect == 3) {
      num = num3; 
      PORTB = B000101;
    } // same as above    this last one could be an else statement too 

    delay (9); // this was here to attempt to remove blur but doesn't completely remove it


    switch (num) { //  MSB is set to 0 for all cases and num is the current displayed digit with active high
    // a small wiring glitch has swapped pins d2 and d7, so the bits below represent numbers in the following
    // order: "portd = b" d2 d6 d5 d4 d3 d7 d1 d0  or  "b f e d c g a -"

    case 0:
      PORTD = B11111010; // number zero or = 0x7E   this outputs to segments on pins 1-7 and pin 0 is always LOW
      break;

    case 1:
      PORTD = B10001000; // number one or = 0x30   hex example
      break;

    case 2:
      PORTD = B10110110; // number two
      break;

    case 3:
      PORTD = B10011110; // number three
      break;

    case 4:
      PORTD = B11001100; // number four
      break;

    case 5:
      PORTD = B01011110; // number five
      break;

    case 6:
      PORTD = B01111110; // number six
      break;

    case 7:
      PORTD = B10001010; // number seven
      break;

    case 8:
      PORTD = B11111110; // number eight
      break;

    case 9:
      PORTD = B11011110; // number nine
      break;

    default:
      PORTD = B00000000; // blank


    } // switch end

  } // for end

} // loop end

When you say "Pretty Short" we would like to know how long, in seconds (or nanoseconds, or picoseconds). You can definitely use an Arduino to count pulses on a line, and they don't always need to be 'slow', its part of the reason we use debounce circuits when dealing with buttons. As long as you are careful about noise sources nearby, you can set up an interrupt on a pin to increment the counter (There is some ways of doing this entirely through hardware, but you might not need to do so). Afterwards a certain amount of time, just update the

Additionally, shift registers are another great way (and usually individually cheaper than BCD->7-Segment ICs) to control 7-Segment displays. You need 1 per 7-Segment, but if you connect them in series (which you usually can) you can load the entire display out to them and not have to worry about muxing everything (requires less pins too). However, 1 BCD may be cheaper than 3 Shift registers (And there is a limit to the current requirements for the 7-Segment Displays).

In my own project, I am using a ULN2003A on a common Anode 7-Segment display, then a 'large' P-Channel MOSFet (Able to handle 200mA), on the common anode of each display. However, this does have the issue of requiring 7+4=11 pins to control the 4x 7-Segment displays, and I would have to add something if I want a Decimal point (which I don't).

Has anyone tried the muxing a single Shift register with multiple 7-Segment displays?

As stated above, although a little obscure, the pulses are of different lengths from the tube and as short at one microsecond. After running through a 555, theyre 500 microseconds. I am controlling 3 seven segment displays using arduino to MUX the segments (direct drive) and 3x 2n3906 pnp's for the common pins. This way arduino doesnt have to sink all those mA, and the voltage drop in the pnp along with a 150 ohm resistor runs the display at a good power level.

The goal is to count pulses over a period of time, and then display a static count on the seven segment displays, refreshing every second. The display end of things is solid, and the total current draw for the circuit displaying "000" (which is all it will display at the moment) is 27 mA as measured in series with the 9volt battery power supply (before the 78L05 regulator im using). The circuit is constructed on a perfboard, using 14 pin sockets for the segments, and a 28 pin socket for the atmel chip. I am running a 20 MHz crystal (without caps at the moment). I will load a schematic at some point, right now the only one I have is on graph paper.

I will fine tune features after I get it working.

Sorry for the multiple posts, just gathering all the info.

Here is a pic of the schematic and of the device (as it will integrate into the geiger counter).

IMG_20130726_141644.jpg

IMG_20130726_141414.jpg

I cannot seem to get the display to increment. Can anyone tell me if I am using millis() in the proper way here?