Menu

mega328p pullup

Help
2017-06-26
2017-07-18
1 2 > >> (Page 1 of 2)
  • stan cartwright

    stan cartwright - 2017-06-26

    Does dir portd.2 in make the pin use it's pull up resistor on mega328p? I am refering to c code that turns the pull up on. DDRD &= ~(1 << DDD2); // Clear the PD2 pin
    // PD2 (PCINT0 pin) is now an input

    PORTD |= (1 << PORTD2);    // turn On the Pull-up
    // PD2 is now an input with pull-up enabled
    

    This code should produce a square wave from portb.0 from a square wave input on portd.2 but doesn't.
    using gcb rc2
    ~~~
    #chip mega328p, 16

    option explicit

    dir portd.2 in ;pcint0 pin
    PCINT0 = 1 ;hardware interrupt on
    dir portb.0 out
    On Interrupt PinChange0 Call pulsout
    do
    loop
    sub pulsout
    portb.0 = !portb.0
    end sub
    ~~~

     

    Last edit: stan cartwright 2017-06-26
  • Chris Roper

    Chris Roper - 2017-06-26

    I don't see where you are setting the pullup in your code but this line should be the equivelent of your C snippet:

    PORTD = PORTD OR FnLSL(1, PORTD2);
    

    I don't use AVR so am not able to test.

    Cheers
    Chris

     
  • Anobium

    Anobium - 2017-06-26

    I do not think this is related to Pullups.

    What is the line of code shown below doing? What is the intent? Have a look at the Help URL also shown below.

    portb.0 = !portb.0

    http://gcbasic.sourceforge.net/help/_inputs_outputs.html

    Once we have resolved this question - if this does not fix the issue then we can have a look at any potential impact of the pullups.

     
  • Anobium

    Anobium - 2017-06-26

    I know this is not related to the pull-ups.

    1. sort the read of portb.0
    2. then, sort the PCINT0 port out
    3. then, when have sorted PCINT0 port out, you will need to change the port in the interrupt handler so you have a different port as you output signal port.
     
  • stan cartwright

    stan cartwright - 2017-06-26

    RE portb.0 = !portb.0 -- I can scope b.0 to check the int is working and NOT won't compile.
    Chris,thanks. You got away with it https://sourceforge.net/p/gcbasic/discussion/579126/thread/32b9f9db/
    I knew << was shift left and | is OR so it's portd = portd or (1<<portd.2).
    So, if portd.2=0 then portd bit 0 is set
    and if portd.2=1 then portd bit 1 is set.
    How does that turn on weak pull ups?
    You don't get this problem cycling..

     

    Last edit: stan cartwright 2017-06-26
  • Anobium

    Anobium - 2017-06-26

    re portb.0 = !portb.0 last January we spent many hours working in the Help to explain how this is NOT the way to read the port. You are currently reading the status of the pull-up.

    portb.0 = !pinb.0 Is the correct method for AVR. Remember?

    This will not make your code work but this is the correct method. This will resolve #1 in my posting above. So, make that change.

    Then, sort #2 and #3.

     
  • Chris Roper

    Chris Roper - 2017-06-26

    It is just part of the AVR hardware architecture.

    The register that controls the Pull ups has the same physical address as the Port.

    When the Port is an output the Pull Ups are inactive and anything written to that address will appear on the output pins.

    When the Port is an input nothing can be output so anything written to that address will set or clear the pullup associated with that pin instead.

     
  • stan cartwright

    stan cartwright - 2017-06-26

    Seems like. I never thought of the microchip 328p data sheet.It's got an index!
    18.2.1. Configuring the Pin. Cheers.

     
  • Anobium

    Anobium - 2017-06-26

    Working example. This is very, very similar to the demonstration in the Interrupt Solution folder..

    #chip mega328p, 16
    #option explicit
    
    dir portb.0 in
    PCINT0 = 1
    
    'set out signal port as an output
    dir portB.5 out
    
    On Interrupt PinChange0 Call TogglePin
    do
    
    loop
    
    sub togglePin
    portb.5 =  !pinb.5
    end sub
    

    The corrections to the code posted are:

    1. Use pin.bit to read a port. See the Help for details. But, essentially portb.5 = !pinb.5 reads and NOT the results to set the port to the NOT status. Even though reading the port may seem to work - always use pin to read. As stated in the Help and the datasheet.
    2. Use the correct pin as the source for PCINT0. As PCINT0 is a interrupt source mask for Portb.0 is is essential the portb.0 is an input.
    3. Change the togglepin, the output signal, to something that is not the input interrupt signal. I have used portb.5

    Validation.

    Connect 1.00Mhz square wave signal to Portb.0 (UNO pin#8) and the output signal will be reflected to the interrupt on Portb.5 (UNO LED pin#13).

    For an input of 1.00Mhz square wave signal you will get a 1.00Mhz square wave signal output.

     
  • stan cartwright

    stan cartwright - 2017-06-27

    Yes,that works.Ta. Faster than my scope I made lots of mistakes from misreading data sheets to testing wrong pins.Wearyness. It seems the on int stuff is figureing data sheets.The working code above would be useful in the help.
    Adding EICRA=0 to 3. Is that enough to change trig on leading edge,trailing,low,any? Scope doesn't show any difference.

     
  • William Roth

    William Roth - 2017-06-27

    @Stan

    I see you have figured out that you were using the wrong interrupt source relative to the pins selected. Since you did not reveal what changes you made to correct the code, I will take a guess and do so.

    If the interrupt source is to be pind.2 then it must be ExtInt0 rather than PCINTO which is on pinb.0.

    The interrupt mask register EICRA determines if the interrupt is on a rising edge, falling edge, low level, or change. I will assume a falling edge with a pullup on Pind,2. Here is what the code should now look like.
    .

    #chip mega328p, 16
    #option explicit
    
    dir portd.2 in        ;//INTO pin
    dir portb.0 out
    
    INT0 = 1              ;// Set INT0 Bit of Mask register (EIMSK)
    EICRA = b'00000010'   ;//  Set int on falling edge
    
    On Interrupt ExtInt0 Call TogglePin
    
    do
       '// Waiting for interrupt  
    loop
    
    sub TogglePin
         portb.0 = !pinb.0
    end sub
    
    END
    
     

    Last edit: William Roth 2017-06-27
  • stan cartwright

    stan cartwright - 2017-06-27

    Thank you Mr Roth for posting that code. I find examples are very useful for learning. Most AVR info is arduino c and converting to GCB is not trivial for me...but so is converting rosettacode other Basic examples.
    I'm just experimenting on ways of making a frequency meter. Pinchange is one way.Using timers is another. I'm interested in pin events stopping timer1 count. I tried this method, it's not accurate but was interesting.Bits of different example code snippets stuck together.I tried scaling the 65535 to 0 timer ,to 0 to 100000 but I think that the wrong way.
    Using leading edge, maybe I could use two pins fed with the same signal. One pin leading edge and starting a timer and the other pin low triggering to stop the timer and measure high time then measure low time by start timer on low trig then stop timer on high trig. Then add results for total period.

      #chip mega328p ;from code examples c/o gcb dev team
      #option explicit
      #include <glcd.h>
        #define GLCD_TYPE GLCD_TYPE_ILI9341
        'Pin mappings for SPI - this GLCD driver supports Hardware SPI and Software SPI
        #define GLCD_DC   portb.2 ;    DIGITAL_10         'HW Data command line DC
        #define GLCD_CS   portd.7 ;    DIGITAL_7          ' Chip select line CS
        #define GLCD_RESET   portd.4 ;      DIGITAL_4         ' Reset line Tie high..not needed
        #define GLCD_DO   portb.3 ;   DIGITAL 11          'HW Data out | MOSI SDI
        #define GLCD_SCK   portb.5 ;   DIGITAL_13          'HW Clock Line SCK
        #define ILI9341_HardwareSPI    ' remove/comment out to use software SPI.
        #define GLCD_EXTENDEDFONTSET1
        GLCDfntDefaultsize = 1
    ;---- init. ----
    dim counter as word
    dim finalcount as word
    finalcount=0
    counter=0
    dir portb.0 in
    PCINT0 = 1
    On Interrupt PinChange0 Call portb0change
    ;
        On Interrupt Timer0Overflow Call every1ms
        ' Initialise the timer - this is required
        ' Set prescaler to 64 and then start the timer
        InitTimer0 Osc, PS_0_64
        ' Start the timer - this is required
        StartTimer 0
    ;---- start ----
    do
    glcdprint (0,20,str(finalcount)+"    ",ILI9341_WHITE)
    wait 100 ms
    loop
    ;----- end -----
    sub portb0change
    counter ++
    End Sub
    'PWM sub
    '---- This will be called when the Timer overflows ----
    Sub every1ms
      ' This sets the TCNT0 register to give us the 1ms Interrupt.
      ' This means there are 255-TCNT0+1 clocks cycles to the next event. Why 1? Becuase the TOP value is 0 not 255.
      Settimer 0, 6 '1.002ms
    ;code here
    finalcount=counter
    counter=0
    End Sub
    
     

    Last edit: stan cartwright 2017-06-27
  • William Roth

    William Roth - 2017-06-27

    For an accurate frequency meter you could count pulses (signal in') for a speciic time period, What what count period is used depends upon the lowest frequency you need to measure.

    Use 1 timer as an external counter. Use another timer to start and stop the first counter for an exact period of time. The number of pulses counted by the first timer during the count period will tell you the frequency.

    Example. Timer 1 (Counter 1) counts 1,000,000 pulses over a period of 1 second, The frequency will obviously be 1 MHz, In order to count millions of pulses, you will need to increment a variable at each rollover of the counter timer via an interrupt,

    So for a signal in of 1MHz, and if the counter timer is a 16-bit timer, it will rollover 15 times and will have a remaining value of 16,960 when stopped at exactly 1 sec.

    15 * 65536 = 983040 ..... 983040 + 16960 = 1,000,000

    If the counter timer is an 8-bit timer it will roll over 3906 times and will have a remainig value of 64 when stopped at exactly 1 sec.

    A 1 second count period will allow measuring frequencies as low as 1 Hz and up to about 50 MHz depending upon the chip used,

     

    Last edit: William Roth 2017-06-27
  • stan cartwright

    stan cartwright - 2017-06-29

    Thanks again. That was the method I was reading about but it's in arduino c :(. It counts the timer 1 overflows from a timer2 1ms gate but uses a pin change to start timer1 which is preloaded.... and it's c.
    I'll try using the method you suggest. I had wondered how it could count so fast. The c code was supposed to be accurate to over 8MHz.

     
  • stan cartwright

    stan cartwright - 2017-06-29

    Mr Roth- "For an accurate frequency meter you could count pulses (signal in') for a speciic time period"
    So... load timer1 with value.
    Start timer1 on pin change.
    count timer1 overflows in 1 ms gate time from timer0
    The c code reset timer1 but I can't find the link :(
    Any tips for Timer1Capture -- An input event on the pin ICP1 has caused the value of Timer 1 to be captured in the ICR1 register -- AVR ... from GCB help would be apreciated by me. I gave up reading other GCB users minds. I like examples.To see is to learn...to do is to know. No see ,no do.
    did I say I don't like c...or python?

     
  • William Roth

    William Roth - 2017-06-29

    Speaking of reading minds ....First you need to clearly define the application.

    1 What frequency measurement range?
    2. What measurement resolution?
    3, Expected accuracy?
    4. What is the max refresh/update rate ? .
    5, What type of input signal. Sine, square, other ?

     
  • stan cartwright

    stan cartwright - 2017-06-30

    It's just an experiment to see different methods from adding pulsein+pulseininv to counting hi/lo time.
    My cheapo usb scopes frequency meter only works to 180 KHz. My multimeters freq range works to 834 KHz. My sig gen only goes to 999999 Hz.
    I suppose 1 to 1000000 Hz would be handy. I can wait 1 second for it to ubdate. I could add a schmitt trigger for a sine wave. Maybe a divider chip as well. Not much use if it's not accurate. Would I% accuracy be optimistic? Like 10V reading 9.9V or 10.1V....1000Hz displaying as 999Hz or 1001Hz.

     
  • William Roth

    William Roth - 2017-07-01

    Below is PIC code that uses the method I described. It is up to you to modify as needed for AVR/UNO. Easily measures from 1 Hz to 2 MHz to a resolution of 1 Hz.
    .

      #chip 16f18346, 32
      #config FEXTOSC = OFF, RSTOSC = HFINT32
      #config MCLRE = ON, WDTE=OFF
    
      #option explicit
    
    
      'Define I2C settings - CHANGE PORTS
      #define I2C_MODE Master
      #define I2C_DATA PORTB.6
      #define I2C_CLOCK PORTB.5
      #define I2C_DISABLE_INTERRUPTS ON
    
      '''Set up LCD
      #define LCD_IO 10
      #define LCD_I2C_Address_1 0x7E
      CLS
    
      Dim Counts as word
      Dim Frequency as Long
    
      '// Configure timer1 as counter on ext pin
      Inittimer1 (EXT, PRE0_1)
      On interrupt Timer1Overflow Call CountOverflows
    
      Do  '// Main Loop
    
          Cleartimer 1
          Counts = 0
          Starttimer 1
    
          '//  These delays determine acquisition time (1 sec)
          '//  This could be handeled by another timer if desired
          '//  Adjust microseconds to calibrate
    
           Wait 1003 ms
           Wait 770 us
    
          Stoptimer 1 '// after exactly 1 sec
    
          '// Calculate Frequency  
          Frequency = Counts * 65536 + timer1
    
          '// Display Result on LCD Display
          Locate 0,0 : Print "Freq: "
          Locate 0,6 : Print Frequency : LCDSPACE 1
          Print "Hz" : LCDSPACE 4
    
      Loop
    
      sub CountOverflows
          Counts++
      End Sub
    
     

    Last edit: William Roth 2017-07-01
  • Paul Haug

    Paul Haug - 2017-07-01

    I would like to comment on Bill's code/comment style. I find his code very clear and very well commented. I often save his code for future reference and to help with GCB statements I have yet to use, in this case "timers".
    Thanks Mr. William Roth, Anobium, and others for all your past help also.
    Paul

     

    Last edit: Paul Haug 2017-07-01
  • stan cartwright

    stan cartwright - 2017-07-02

    Works on mega328p with header and delete next 2 lines.
    PortD.5 is input.
    I didn't know Inittimer1 (EXT, PRE0_1), I was going to use TCCR1B = TCCR1B OR 0B00000111, or cs12=1:cs11=1:cs10=1 which do the same and easier for me to find.
    65184 Hz gave frequency as 65535. I Hz higher gives 0 Hz.
    Handy code, cheers.

     
  • William Roth

    William Roth - 2017-07-02

    You get to know GCB and its commands by reading the Help, programming a chip with code and testing/debugging. Certainly "inittimer1" is not that hard to find in the help file.

    If the ouput goes from 65535 to zero, then there is an error in the code. Post the code and we will sort it out.

     

    Last edit: William Roth 2017-07-02
  • stan cartwright

    stan cartwright - 2017-07-02

    I changed counts to long but then frequency is same 5 digit number.. 28xxx.
    I'd like more detail in the help when it comes to setting the timers up and the names used for changing relevent registers used and GCB key words used to do that. Searching for info it seems other people find interpretting data sheets bit difficult to. There's plenty of commented c code to examine but I don't follow c easily.

    #chip mega328p, 16
    #option explicit
    #include <glcd.h>
    ;
    #define GLCD_TYPE GLCD_TYPE_ILI9341
    #define GLCD_DC   portb.2 ;    DIGITAL_10
    #define GLCD_CS   portd.7 ;    DIGITAL_7  
    #define GLCD_RESET   portd.4 ;      DIGITAL_4         ' Reset line Tie high..not needed
    #define GLCD_DO   portb.3
    #define GLCD_SCK   portb.5
    #define ILI9341_HardwareSPI
    #define GLCD_EXTENDEDFONTSET1
    GLCDfntDefaultsize = 2
    GLCDRotate (landscape)
    ;
    Dim Counts as word
    Dim Frequency as Long
    ;Inittimer1 (EXT, PRE0_1) ; THIS IS NOT EXPLAINED IN HELP
    ;TCCR1B = TCCR1B or 0B00000111 ;set CS12, CS11 and CS10 to "1" port d.5 input
    cs12=1:cs11=1:cs10=1
    On interrupt Timer1Overflow Call CountOverflows
    
      Do  '// Main Loop
    
          Cleartimer 1
          Counts = 0
          Starttimer 1
    
          '//  These delays determine acquisition time (1 sec)
          '//  This could be handeled by another timer if desired
          '//  Adjust microseconds to calibrate
    
           Wait 1000 ms
            ;wait 770 us
    
          Stoptimer 1 '// after exactly 1 sec
    
          '// Calculate Frequency
          Frequency = Counts * 65535 + timer1
    
    glcdPrint (0,0,"Frequency",ILI9341_YELLOW)
    glcdPrint (0,16,str(Frequency)+" Hz   ",ILI9341_AQUA)
      Loop
    
      sub CountOverflows
          Counts++
      End Sub
    
     
  • William Roth

    William Roth - 2017-07-02

    @Stan
    @All

    It seems that using "++" to increment a variable only works for PIC Microcontrollers. In the code above change "Counts++" to "Counts = Counts + 1" .

     
  • William Roth

    William Roth - 2017-07-02

    Stan,

    Change Counts++ to Counts = Counts + 1. This is a compiler issue.

    Bill

     

    Last edit: William Roth 2017-07-02
  • William Roth

    William Roth - 2017-07-02

    Stan, the attached code works well and was tested from 15 Hz to 4 MHz. Add your GLCD stuff as necessary.

    I noticed that for some unown reason you changed the calculation to use 65535 as the count multiplier, You should not do this. "0" is a "whole number" and is included in the counting. Use 65536 as in the the attached code. If accuracy needs to be tuned , do that with the 1 sec delay period instead.

     
1 2 > >> (Page 1 of 2)

Log in to post a comment.

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.