• Missing external USB D+ pullup on STM32 powered PCB

    kevarek03/09/2019 at 18:09 3 comments

    This is not fail as such, but I believe it is good lesson learned and also trick to have in a sleeve, so I will publish it here (maybe just for future myself being lost again).

    When connecting MCU to PC via USB, it is quite useful to fit external pull-up resistor in series with MCU controlled PFET to 3.3V supply. This allows you to turn the pull-up off and on during MCU boot and inform USB hub to re-enumerate your device without re-inserting the connector (for instance during debugging sessions).

    A USB device must indicate its speed by pulling either the D+ or D- line high to 3.3 volts. A full speed device, pictured below will use a pull up resistor attached to D+ to specify itself as a full speed device. These pull up resistors at the device end will also be used by the host or hub to detect the presence of a device connected to its port. Without a pull up resistor, USB assumes there is nothing connected to the bus. Some devices have this resistor built into its silicon, which can be turned on and off under firmware control, others require an external resistor.
    Im typically doing it like this:Well few days ago, while reusing one of my very old and obsolete PCB without external switchable pull-up, I had to write new firmware and each debug session start I had to re-insert the connector, which was mind numbing and after some time I started to look for software workaround. Im not sure whether this is USB compliant hack, but it certainly works.
    Before initializing USB peripheral in MCU, D+ pin (USBP) is configured as GPIO output push-pull and set low (0V) for 5ms. After that standard USB configuration including GPIO is performed. After this procedure USB host recognizes new device and starts enumeration.
                           LL Driver Callbacks (PCD -> USB Device Library)
    /* MSP Init */
    void HAL_PCD_MspInit(PCD_HandleTypeDef* pcdHandle)
      GPIO_InitTypeDef GPIO_InitStruct;
      /* USER CODE BEGIN USB_MspInit 0 */
        GPIO_InitStruct.Pin = GPIO_PIN_12;
        GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
        GPIO_InitStruct.Pull = GPIO_NOPULL;
        GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
        HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
      /* USER CODE END USB_MspInit 0 */
        /**USB GPIO Configuration    
        PA11     ------> USB_DM
        PA12     ------> USB_DP 
        GPIO_InitStruct.Pin = GPIO_PIN_11|GPIO_PIN_12;
        GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
        GPIO_InitStruct.Pull = GPIO_NOPULL;
        GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
        GPIO_InitStruct.Alternate = GPIO_AF14_USB;
        HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
        /* Peripheral clock enable */
        /* Peripheral interrupt init */
        HAL_NVIC_SetPriority(USB_LP_IRQn, 5, 0);
      /* USER CODE BEGIN USB_MspInit 1 */
      /* USER CODE END USB_MspInit 1 */

     I hope this helps someone in the future. Im wondering whether this is fully compliant routine to re-enumerate USB device and Im using external pull-up and PFET all the time redundantly? Please comment if you know the answer :)

  • A differential ADC will measure the voltage difference between two pins. Maybe :)

    kevarek02/09/2017 at 20:33 3 comments

    The goal was to convert signal 0 - 5V centered around 2.5V. It was evaluation of better ADC for precise measurement instrument. AD7691 18-bit SAR ADC was chosen. Nice differential input, 250ksps, great linearity, low errors. I made gain calibrations (real output voltage vs adc measured voltage) for the instrument and the results were shocking. Upper 25% of range was bullshit ( stuck codes, missing codes, even codes that corresponds to 19bit ADC :) ) and measurement was not to be trusted. Hmm I have probably damaged internal circuitry by accidentally increasing VDD to 8V for short period of time. But changing ADC didnt help. Problem was elsewhere.

    I have found one guy who dealed with similar behavior but without any solution

    ( http://electronics.stackexchange.com/questions/114825/stuck-codes-in-samples-from-adc )

    Visiting datasheet again I have found one funky value I wasnt checking during the design because I have expected common mode range to be 0 to VREF, but LOL it is VREF/2+-0.1V. This means that I cannot feed VREF/2 signal to negative ADC input, but negative copy of my signal centered around VREF/2 instead.

    What is going on? Apparently there is a lof of types of ADC inputs, which you can and should study in the very nice document from LT: http://cds.linear.com/docs/en/product-selector-card/2PB_sarinputtypesfb.pdf, but be careful AD uses slightly different terminology.

    Long story short AD7691 is true(fully) differential unipolar ADC and my signal was for pseudo-differential bipolar ADC or true differential with wide common mode ADC :-)

    Solution was easy. Adding inverting "voltage follower" biased at VREF/2 (original signal is also biased at VREF/2). There are much nicer solutions but this was quick solution for very low frequencies, so it is OK.

    Simulation says it works, common mode is in range.

    Solved :)

  • I will make that low pass filter of second order without any reason fail

    kevarek02/09/2017 at 19:01 0 comments

    When I was working on one of my projects I needed to filter analog signal above 10Hz... or above 1000Hz... whatever. Well I decided to add a second order low pass filter instead of simple first order to get rid of that ugly and nasty noise :)

    General Sallen-Key low pass filter topology is nice, with some symmetry it is very easy to calculate gain, time constant and other stuff. It was working as expected until variable gain possibility was added.

    Here Im going to mention filter quality factor Q which is a design parameter of filters. Q provides a measure of sharpness to the stage frequency response. High Q implies a very narrow sharp frequency response. Low Q provides a wide shallow frequency response. But high Q makes an oscillator from your filter, which I wasnt aware of :) See below what I have designed and constructed and the simulation in LTSpice (great piece of software - thank you guys) of a violent oscillations with higher gain :) Transient simulation of frist 250ms after startup, while stepping feedback resistor value to set gains to 1x, 2x, 3x, 4x, 5x, 6x. Anything above 2x oscillates.

    Simulated frequency response of my filter should tell us more. Note that this is the same circuit but without opamp supply voltage limitation ( I had to add supply voltage limit so you can see something else than infinite oscillations on the picture above).

    Frequency simulation from 0.1Hz to 100Hz for same gains reveals the reason. The filter with gain 2x tends to amplify extremely frequency about 10.5Hz, phase shift goes above 180° (not present on plot above) and positive feedback via C2 causes the oscillations.

    Making the filter of first order (as I should have done from the beginning) just solves all the trouble. Making the C2 smaller and R1 higher works as well.

    This was just an inspiration to see what can go wrong with active filters of higher order. I recommend you to read free document from Texas Instruments: Active Filter Design Techniques (excerpted from op amps for everyone).


  • Solder paste wont be easily cleaned from PCB after reflow in oven

    kevarek02/09/2017 at 18:13 3 comments

    This is just a quick starter or project icebreaker :) Maybe more fun, but in reality it was fail because I was very naive thinking I will spread thin layer of solder paste all over the PCB, place all the components and reflow it in oven and clean all the remaining peaces of unused solder.

    Well you can see the fruit of my naiveness on the picture below. Dont do it, it wasnt possible to clean the board at all :)