Author Topic: PIC16F1946 - Hardware SPI timing issues?  (Read 4905 times)

0 Members and 1 Guest are viewing this topic.

Offline nexusTopic starter

  • Regular Contributor
  • *
  • Posts: 194
  • Country: us
Re: PIC16F1946 - Hardware SPI timing issues?
« Reply #25 on: November 12, 2022, 05:45:11 am »
From the first 'scope plot, your clock has the wrong polarity/phase. You should have positive going pulse when transferring data.


I see. I reversed the clock polarity by setting bit 4 in SSP1CON1. This is my initialization code now:

Code: [Select]
uint8_t max31865_interface_spi_init(void)
{
    SSP1CON1 = (0<<5); //clear bit 5, disable serial port
   
    TRISC = (0<<3) | (1<<4) | (0<<5) | (0<<6); //clear RC3, RC5, RC6 (output: SCK1, SDO, CS) and set RC4 (input: SDI)
    SSP1CON1 = (1<<4) | (0<<3) | (0<<2) | (0<<1) | (0<<0); // 4: (CKP), 3-0:(SSPM = 0000; Master mode , Fosc/4)
    SSP1STAT = (0<<7) | (0<<6); //7: (SMP) 1-end, 0-middle, 6: (CKE) transmit on clock transition to active
    SSP1ADD = 0;
   
    SSP1CON1 = (1<<5); //set bit 5, enable serial port
   
return 0;
}

CKE (SSP1STAT bit 6) is still cleared (0 - Transmit occurs on transition from Idle to active clock state)

This is what happens when the code first initializes and runs the "max31865_shot_init" function.



Interestingly, SDO is appears to go high after the last clock cycle and then decays, almost capacatively.

The polling "max31865_shot_read" function in the while loops looks like this:



The same decay happens on SDO after the 16th clock cycle. It actually goes high when the last CLK pulse occurs, the decays.
Perhaps the "gap" between the first 8 and last 8 clock cycles is too large, and the max is beginning to write serial data after the last 8 clock cycles?
 

Offline NorthGuy

  • Super Contributor
  • ***
  • Posts: 3138
  • Country: ca
Re: PIC16F1946 - Hardware SPI timing issues?
« Reply #26 on: November 12, 2022, 06:10:38 am »
SDO (also called MOSI) is driven by the PIC. SDI (MISO) is driven by Max. Check your connections. Do you have anything else connected to these pins.

Also, whewn you write this:

Code: [Select]
SSP1CON1 = (1<<5); //set bit 5, enable serial port
you overwrite all the bits of the register. It's the same as if you wrote

Code: [Select]
SSP1CON1 = 0x20; //set bit 5, enable serial port
It does set the 5-th bit to 1, but alse reset all the other bits to 0. What you need is this:

Code: [Select]
SSP1CON1 |= (1<<5); //set bit 5, enable serial port
or this:

Code: [Select]
SSP1CON1bits.SSPEN = 1; //set bit 5, enable serial port


 

Offline DavidAlfa

  • Super Contributor
  • ***
  • Posts: 5890
  • Country: es
Re: PIC16F1946 - Hardware SPI timing issues?
« Reply #27 on: November 12, 2022, 07:27:15 am »
Your code is overcomplicated.
The MAX31865 only reads/write one byte for each register, so there's little sense on using a pointer to the buffer and data length.
Also the two sepparate read/write functions are 99% redundant, that's why I showed how to unify them, the result will be the same.
Why are you setting CKE low? You've been warned about the errata, also CKP=0,CKE=1 is the most common SPI mode.
Why so many functions always returning 0 when there're no checks of any kind, or anything else to return? Just make them void.
The delay_ms function is redundant, simply use __delay_ms();
Remember for the delay to work correctly, _XTAL_FREQ must be defined somewhere, matching the crystal frequency in Hz.
You're defining it as 1MHz, is that correct? Seems too low?

Writing SSPBUF before clearing SSP1IF will make it a bit faster, as the transmission starts earlier.
Code: [Select]
void max31865_interface_spi_init(void)
{
    TRISC    = 1<<4;          // Clear RC3, RC5, RC6 (output: SCK1, SDO, CS) and set RC4 (input: SDI)
    SSP1CON1 = 0;
    SSP1STAT = 0;
    SSP1ADD  = 0;
    CKE1     = 1;             // Transmit from idle to active transition
    SSPEN1   = 1;             // Enable serial port
}

void max31865_interface_spi_deinit(void)
{
    SSPEN1=0;                 // Disable serial port
}

uint8_t max31865_interface_spi_readwrite(uint8_t reg, uint8_t data)
{
    LATC6 = 0;                // CS low
    NOP();                    // Small delay
    SSP1BUF = reg;            // Send address
    while(!SSP1IF);           // Wait
    SSP1BUF = data;           // Send data (Or dummy byte in read mode)
    SSP1IF = 0;               // Clear flag
    while(!SSP1IF);SSP1IF=0;  // Wait, clear flag
    LATC6 = 1;                // CS high
    return SSP1BUF;           // Return received data if any (Ignore in write mode)
}

Image test:
Code: [Select]
max31865_interface_spi_readwrite(0x99,0xAA);
« Last Edit: November 12, 2022, 09:32:33 am by DavidAlfa »
Hantek DSO2x1x            Drive        FAQ          DON'T BUY HANTEK! (Aka HALF-MADE)
Stm32 Soldering FW      Forum      Github      Donate
 

Offline nexusTopic starter

  • Regular Contributor
  • *
  • Posts: 194
  • Country: us
Re: PIC16F1946 - Hardware SPI timing issues?
« Reply #28 on: November 20, 2022, 02:58:41 am »
Coming back to this after another exhausting week.

SDO (also called MOSI) is driven by the PIC. SDI (MISO) is driven by Max. Check your connections. Do you have anything else connected to these pins.

Also, whewn you write this:

Code: [Select]
SSP1CON1 = (1<<5); //set bit 5, enable serial port
you overwrite all the bits of the register. It's the same as if you wrote


I see, thank you for pointing this out. I changed the code such that I am not clearing any bits that were previously set accidently.

Your code is overcomplicated.
The MAX31865 only reads/write one byte for each register, so there's little sense on using a pointer to the buffer and data length.
Also the two sepparate read/write functions are 99% redundant, that's why I showed how to unify them, the result will be the same.
Why are you setting CKE low? You've been warned about the errata, also CKP=0,CKE=1 is the most common SPI mode.
Why so many functions always returning 0 when there're no checks of any kind, or anything else to return? Just make them void.
The delay_ms function is redundant, simply use __delay_ms();
Remember for the delay to work correctly, _XTAL_FREQ must be defined somewhere, matching the crystal frequency in Hz.
You're defining it as 1MHz, is that correct? Seems too low?

I did change it to CKP = 0 and CKE = 1 to avoid the errata; thank you for pointing this out (again). I also consolidated everything to the single read/write duplex function as you suggested. The "return 0" was a part of the max31865 library I was attempting to use. I discarded the library as you will see below and I'm trying to make my code as simple as possible so I can first understand what is (or isn't) working.

I am running the Fosc at 1MHz, so CLK is 250 kHz (Fosc/4). I don't think running on the slower side should somehow "break" SPI?

Keeping things as simple as possible, here is what I am trying:

Code: [Select]
/*
 * File:   max_test_1.c
 * Author: kev
 *
 * Created on November 6, 2022, 1:05 PM
 */


#include <xc.h>
#include <stdint.h>
#include <stdio.h>
#include "configs.h"
#define _XTAL_FREQ 1000000

void spi_init(){
    SSP1CON1 = (0<<5); //clear bit 5, disable serial port
   
    TRISC = (0<<3) | (1<<4) | (0<<5) | (0<<6); //clear RC3, RC5, RC6 (output: SCK1, SDO, CS) and set RC4 (input: SDI)
    SSP1CON1 = (0<<4) | (0<<3) | (0<<2) | (0<<1) | (0<<0); // 4: (CKP), 3-0:(SSPM = 0000; Master mode , Fosc/4)
    SSP1STAT = (0<<7) | (1<<6); //6: (CKE) transmit on clock transition to active
    SSP1ADD = 0;
   
    SSP1CON1bits.SSPEN = 1; //set bit 5, enable serial port
   
}

uint8_t max31865_interface_spi_readwrite(uint8_t reg, uint8_t data)
{
    LATCbits.LATC6 = 0;       // CS low
    NOP();                    // Small delay
    SSP1BUF = reg;            // Send address
    while(!SSP1IF);           // Wait
    SSP1BUF = data;           // Send data (Or dummy byte in read mode)
    PIR1bits.SSP1IF = 0;      // Clear flag
    while(!SSP1IF);SSP1IF=0;  // Wait, clear flag
    LATCbits.LATC6 = 1;       // CS low
    return SSP1BUF;           // Return received data if any (Ignore in write mode)
}


void main(void) {
    spi_init();
    OSCCONbits.IRCF = 0x0B; //set internal osc to 1mhz
    OSCCONbits.SCS = 0x00; //system clock setup
   
    max31865_interface_spi_readwrite(0x00,0x62);
    __delay_ms(100);
   
    while (1){
        max31865_interface_spi_readwrite(0x01,0x00); //read RTD MSBs
        max31865_interface_spi_readwrite(0x02,0x00); //read RTD LSBs
//        max31865_interface_spi_readwrite(0x03,0x00); //read high fault threshold status
//        max31865_interface_spi_readwrite(0x04,0x00); //read low fault threshold status
//        max31865_interface_spi_readwrite(0x05,0x00); //read low fault threshold MSB
//        max31865_interface_spi_readwrite(0x06,0x00); //read low fault threshold LSB
//        max31865_interface_spi_readwrite(0x07,0x00); //read fault status
        __delay_ms(1000);
    }
}

The first command is to set the configuration register:  max31865_interface_spi_readwrite(0x00,0x62). Here's what that looks like on the scope:



The second two commands which run once a second in the while loop are to read the RTD MSB and LSB registers. Here's what that looks like on scope:



I have a tested PT100 hooked up across the RTD. My board is using a 400 Ohm reference resistor. Also attached full schematic project in case something here is obviously wrong, which I don't believe it is since I am using the MAX31865 reference design and I'm sure I have the SPI pins mapped correctly between the PIC and this chip.



What I'm not sure of is the data that I'm reading from the MAX31865 on SDO. The RTD MSB register reads empty. The RTD LSB register is all high, and there is this strange decay during the end of each transmission. It looks to be capacitive, which I don't understand.

Also, when I plug and unplug my RTD, nothing changes in the RTD MSB/LSB data from what I can see.

Room temperature (20C) for the PT100 with a 400 Ohm Rreference should yield the following data from the RTD registers:



Do I need to set the fault threshold registers as well? I don't see anything else that could be wrong here.
I also replaced the MAX31865 chip. Digikey was out of stock when I first made the board, so I bought a breakout on eBay to get the part. Now that the QFN20 package is in stock again I ordered 10 brand new ones, so I'm sure the chip itself is genuine and functional.
 

Offline DavidAlfa

  • Super Contributor
  • ***
  • Posts: 5890
  • Country: es
Re: PIC16F1946 - Hardware SPI timing issues?
« Reply #29 on: November 20, 2022, 05:37:25 am »
The decay is normal, SDO becomes hi-z when chip is not active, PIC input has high impedance too, so it takes a bit to discharge.
If you really need to get rid of it, add a 10K pulldown resistor to SDO.
« Last Edit: November 20, 2022, 05:38:57 am by DavidAlfa »
Hantek DSO2x1x            Drive        FAQ          DON'T BUY HANTEK! (Aka HALF-MADE)
Stm32 Soldering FW      Forum      Github      Donate
 

Offline NorthGuy

  • Super Contributor
  • ***
  • Posts: 3138
  • Country: ca
Re: PIC16F1946 - Hardware SPI timing issues?
« Reply #30 on: November 20, 2022, 02:50:38 pm »
Coming back to this after another exhausting week.

I looked at the datasheet.

In your communications, everything appears to be shifted by 1 bit. You're reading register 0x04 instead of 0x02, hence you get all ones. The response is shifted right by 1 bit too - 0x7f instead of 0xff. So, your SPI mode is wrong. Looking at their pictures in the datasheet, you need CKE = 0. The datasheet claims CKP doesn't matter (see Fig. 5). You have CKP = 0, CKE = 1.

Also, it will not do any conversions on its own. You can do either automatic conversions, or one shot conversion. Either way, you need to write to the configuration register to get anything out of the chip. Read the datasheet for details.

 

Offline jpanhalt

  • Super Contributor
  • ***
  • Posts: 3455
  • Country: us
Re: PIC16F1946 - Hardware SPI timing issues?
« Reply #31 on: November 20, 2022, 04:27:16 pm »
In your communications, everything appears to be shifted by 1 bit. You're reading register 0x04 instead of 0x02, hence you get all ones. The response is shifted right by 1 bit too - 0x7f instead of 0xff. So, your SPI mode is wrong. Looking at their pictures in the datasheet, you need CKE = 0. The datasheet claims CKP doesn't matter (see Fig. 5). You have CKP = 0, CKE = 1.

Ah, deja vu post #17 & 19.
 

Offline DavidAlfa

  • Super Contributor
  • ***
  • Posts: 5890
  • Country: es
Re: PIC16F1946 - Hardware SPI timing issues?
« Reply #32 on: November 20, 2022, 06:49:52 pm »
Doesn't look shifted to me, I clearly see how SDO changes on the previous falling edge, sending 1 & 2.
Hantek DSO2x1x            Drive        FAQ          DON'T BUY HANTEK! (Aka HALF-MADE)
Stm32 Soldering FW      Forum      Github      Donate
 

Offline NorthGuy

  • Super Contributor
  • ***
  • Posts: 3138
  • Country: ca
Re: PIC16F1946 - Hardware SPI timing issues?
« Reply #33 on: November 21, 2022, 05:16:42 am »
Doesn't look shifted to me, I clearly see how SDO changes on the previous falling edge, sending 1 & 2.

Sure. But the MAX device expects CKE = 0, so it sees it shifted.
 

Offline DavidAlfa

  • Super Contributor
  • ***
  • Posts: 5890
  • Country: es
Re: PIC16F1946 - Hardware SPI timing issues?
« Reply #34 on: November 21, 2022, 05:54:57 am »
Nope:

The MAX31865 automatically accommodates either clock polarity by sampling SCLK when CS becomes active to determine the polarity of the inactive clock
« Last Edit: November 21, 2022, 05:56:41 am by DavidAlfa »
Hantek DSO2x1x            Drive        FAQ          DON'T BUY HANTEK! (Aka HALF-MADE)
Stm32 Soldering FW      Forum      Github      Donate
 

Offline jpanhalt

  • Super Contributor
  • ***
  • Posts: 3455
  • Country: us
Re: PIC16F1946 - Hardware SPI timing issues?
« Reply #35 on: November 21, 2022, 11:29:59 am »
The MAX31865 (and its related chips for thermocouples) only works SPI modes 1 and 3.  I documented that fact experimentally with the MAX31856.

From MAX31865 datasheet page 16 (attachment):
 

Offline DavidAlfa

  • Super Contributor
  • ***
  • Posts: 5890
  • Country: es
Re: PIC16F1946 - Hardware SPI timing issues?
« Reply #36 on: November 21, 2022, 12:07:52 pm »
Damn, I got the spi modes backwards, you're right  :-X
So yeah:
CKE=0,
CKP=0 (Mode 1) or CKP=1(Mode 3)
« Last Edit: November 21, 2022, 12:10:02 pm by DavidAlfa »
Hantek DSO2x1x            Drive        FAQ          DON'T BUY HANTEK! (Aka HALF-MADE)
Stm32 Soldering FW      Forum      Github      Donate
 

Offline jpanhalt

  • Super Contributor
  • ***
  • Posts: 3455
  • Country: us
Re: PIC16F1946 - Hardware SPI timing issues?
« Reply #37 on: November 21, 2022, 12:20:20 pm »
Remember (post #8) that when CKE=0, the errata for the PIC16F1946 BF comes into play.  That errata does not apply to the 16F18xx or 16F17xx chips so far as I know.  That is based on my experience with a few examples in those latter series. I have not checked every chip in those latter series, however.
 

Offline nexusTopic starter

  • Regular Contributor
  • *
  • Posts: 194
  • Country: us
Re: PIC16F1946 - Hardware SPI timing issues?
« Reply #38 on: November 24, 2022, 04:19:07 am »
Good news, I believe the SPI is somewhat working now.

One mistake I found was that I kept trying to write to the config read register (0x00) instead of the actual write address (0x80). Doh!

Another thing I realized is that I need to have 24 clock cycles to do a complete read of the RTD registers; 8 to write the register address, and 16 for the full 16 bits of data in the MSB temperature measurement register.

Here is the code that works as far as setting the config and doing a 1 shot measurement by setting and clearing the 1-shot bit (D5):

Code: [Select]
#include <xc.h>
#include <stdint.h>
#include <stdio.h>
#include "configs.h"
#define _XTAL_FREQ 1000000

void spi_init(){
    SSP1CON1 = (0<<5); //clear bit 5, disable serial port
   
    TRISC = (0<<3) | (1<<4) | (0<<5) | (0<<6)| (0<<6); //clear RC3, RC5, RC6 (output: SCK1, SDO, CS) and set RC4, RC7 (input: SDI, MAX RDY)
    SSP1CON1 = (1<<4) | (0<<3) | (0<<2) | (0<<1) | (0<<0); // 4: (CKP), 3-0:(SSPM = 0000; Master mode , Fosc/4)
    SSP1STAT = (0<<7) | (0<<6); //7 (SPI Master mode), 0 = Input data sampled at middle of data output time, 6: (CKE) transmit on clock transition to active
    SSP1ADD = 0;
   
    SSP1CON1bits.SSPEN = 1; //set bit 5, enable serial port
   
}

uint8_t max31865_interface_spi_readwrite(uint8_t reg, uint8_t data)
{
    LATCbits.LATC6 = 0;       // CS low
    NOP();                    // Small delay
    SSP1BUF = reg;           // Send address
    while(!PIR1bits.SSP1IF);  // Wait
    PIR1bits.SSP1IF = 0;
    SSP1BUF = data;           // Send dummy byte / data
    while(!PIR1bits.SSP1IF);  // Wait
    PIR1bits.SSP1IF = 0;
    SSP1BUF = data;           // Send dummy byte / data
    while(!PIR1bits.SSP1IF);  // Wait
    PIR1bits.SSP1IF = 0;
    LATCbits.LATC6 = 1;       // CS high
    return SSP1BUF;           // Return received data
}

void main(void) {
    spi_init();
    OSCCONbits.IRCF = 0x0B; //set internal osc to 1mhz
    OSCCONbits.SCS = 0x00; //system clock setup
   
    max31865_interface_spi_readwrite(0x80,0xA0); //config register write addr: 0x80. set config register bits 1000000 = 0x80
    __delay_ms(100);
   
    while (1){
        max31865_interface_spi_readwrite(0x80,0xA8); //set 1-shot bit to trigger conversion (D5)
        max31865_interface_spi_readwrite(0x01,0x00); //read RTD MSBs
//        max31865_interface_spi_readwrite(0x02,0x00); //read RTD LSBs
        max31865_interface_spi_readwrite(0x80,0xA0); //clear 1-shot bit (D5)
//        max31865_interface_spi_readwrite(0x03,0x00); //read high fault threshold status
//        max31865_interface_spi_readwrite(0x04,0x00); //read low fault threshold status
//        max31865_interface_spi_readwrite(0x05,0x00); //read low fault threshold MSB
//        max31865_interface_spi_readwrite(0x06,0x00); //read low fault threshold LSB
//        max31865_interface_spi_readwrite(0x07,0x00); //read fault status
        __delay_ms(1000);
    }
}



I have serial decode set up on the scope so you can clearly see what data is being transacted between the PIC and the MAX.

Now one challenge I am having to read the data is to create a buffer for SSP1BUF. Since I need to read all 16 bits, and SSP1BUF is only 8 bits and cleared in the middle of the read, I need to capture all 16 bits of the two SSP1BUF reads into a single variable as the code executes..
« Last Edit: November 24, 2022, 04:31:37 am by nexus »
 

Offline DavidAlfa

  • Super Contributor
  • ***
  • Posts: 5890
  • Country: es
Re: PIC16F1946 - Hardware SPI timing issues?
« Reply #39 on: November 24, 2022, 04:54:01 am »
Why sending/receiving 2 data bytes?
Code: [Select]
uint8_t max31865_interface_spi_readwrite(uint8_t reg, uint8_t data)
{
    LATCbits.LATC6 = 0;       // CS low
    NOP();                    // Small delay
    SSP1BUF = reg;           // Send address
    while(!PIR1bits.SSP1IF);  // Wait
    PIR1bits.SSP1IF = 0;
    SSP1BUF = data;           // Send dummy byte / data
    while(!PIR1bits.SSP1IF);  // Wait
    PIR1bits.SSP1IF = 0;
    SSP1BUF = data;           // Send dummy byte / data  <<--------- ?????
    while(!PIR1bits.SSP1IF);  // Wait
    PIR1bits.SSP1IF = 0;
    LATCbits.LATC6 = 1;       // CS high
    return SSP1BUF;           // Return received data
}

Just make two readings and pack the data into a 16-bit variable:
Code: [Select]
uint8_t max31865_interface_spi_readwrite(uint8_t reg, uint8_t data)
{
    LATCbits.LATC6 = 0;       // CS low
    NOP();                    // Small delay
    SSP1BUF = reg;           // Send address
    while(!PIR1bits.SSP1IF);  // Wait
    PIR1bits.SSP1IF = 0;
    SSP1BUF = data;           // Send dummy byte / data
    while(!PIR1bits.SSP1IF);  // Wait
    PIR1bits.SSP1IF = 0;
    LATCbits.LATC6 = 1;       // CS high
    return SSP1BUF;           // Return received data
}

uint16_t read_rtd(void)
{
    uint16_t rtd = max31865_interface_spi_readwrite(0x01,0x00); //read RTD MSBs
    rtd = rtd<<8 | max31865_interface_spi_readwrite(0x02,0x00); //read RTD LSBs
    return rtd;
}
« Last Edit: November 24, 2022, 05:07:45 am by DavidAlfa »
Hantek DSO2x1x            Drive        FAQ          DON'T BUY HANTEK! (Aka HALF-MADE)
Stm32 Soldering FW      Forum      Github      Donate
 

Offline NorthGuy

  • Super Contributor
  • ***
  • Posts: 3138
  • Country: ca
Re: PIC16F1946 - Hardware SPI timing issues?
« Reply #40 on: November 24, 2022, 04:28:31 pm »
Another thing I realized is that I need to have 24 clock cycles to do a complete read of the RTD registers; 8 to write the register address, and 16 for the full 16 bits of data in the MSB temperature measurement register.

Not necessarily, you can read each half separately.

But you certainly can read two bytes at once, a la:

Code: [Select]
uint16_t max31865_interface_spi_read16(uint8_t reg)
{
    uint8_t temp;

    LATCbits.LATC6 = 0;       // CS low
    NOP();                    // Small delay

    SSP1BUF = reg;           // Send address
    while(!PIR1bits.SSP1IF);  // Wait
    PIR1bits.SSP1IF = 0;

    SSP1BUF = 0;           // Send dummy byte
    while(!PIR1bits.SSP1IF);  // Wait
    PIR1bits.SSP1IF = 0;
    temp = SSP1BUF;

    SSP1BUF = 0;           // Send dummy byte
    while(!PIR1bits.SSP1IF);  // Wait
    PIR1bits.SSP1IF = 0;

    LATCbits.LATC6 = 1;       // CS high

    return (SSP1BUF << 8) | temp;           // Return received data
}
 

Offline nexusTopic starter

  • Regular Contributor
  • *
  • Posts: 194
  • Country: us
Re: PIC16F1946 - Hardware SPI timing issues?
« Reply #41 on: November 27, 2022, 05:19:49 am »
Finally, I think I've reached the finish line on this project. Thank you for all the tips!

The SPI was the biggest software hurdle for me since I had never used the hardware peripheral on a PIC, never used the MAX 31865 before, and in general am still a beginner.

The program is right up against the memory limit for the PIC16F1946 when compiled using XC8 free v2.40. Attached main.c. It's not the prettiest code (I'm still a mechanical engineer on paper), but it works.

Code: [Select]
Memory Summary:
    Program space        used  1FC4h (  8132) of  2000h words   ( 99.3%)
    Data space           used   1D3h (   467) of   200h bytes   ( 91.2%)
    EEPROM space         used     0h (     0) of   100h bytes   (  0.0%)
    Configuration bits   used     2h (     2) of     2h words   (100.0%)
    ID Location space    used     4h (     4) of     4h bytes   (100.0%)

I would have used the 16F1947 with twice the internal storage and RAM but none were in stock on digikey and mouser. I could always upgrade with a simple swap as I believe they are identical outside of the memory size difference.

I will do a proper writeup on my project site https://neonkev.com/.

The metalwork was also completely custom. I designed the box in CAD and had it made by PCBway along with the boards. 316 stainless sheet with press fit PEM inserts. All M3 fasteners.

For now, a quick demo of what this whole thing was about: a power supply for the Vision Engineering C073 14 point LED illuminator. It drives two separate strings of 7 high power LEDs, the 12V cooling fan, and reads the internal PT100 RTD in the LED heatsink to monitor temp. Brightness is controlled by PWM through the PIC and the rotary encoder. Push button for the encoder turns the main power on and off via relay to the LED driver ICs (MPM6010).

I upgraded the fans in the light head and power supply to PWM controlled ones as well.
They are autonomous by use of independent temperature controlled drivers: https://www.ebay.com/itm/284526780525

LEDs on the original C073 ring light were also upgraded to the latest Luxeon star rebel LEDs, 235lm @ 700mA: https://www.luxeonstar.com/cool-white-5650K-sinkpad-ii-20mm-star-led-module-235lm

Quick demo vid:
« Last Edit: November 27, 2022, 05:34:58 am by nexus »
 
The following users thanked this post: DavidAlfa

Offline DavidAlfa

  • Super Contributor
  • ***
  • Posts: 5890
  • Country: es
Re: PIC16F1946 - Hardware SPI timing issues?
« Reply #42 on: November 27, 2022, 05:50:13 am »
Ensure to enable optimizations, O2 is free and will reduce the memory usage a lot.

So you're "only” a mechanical enginneer but did that? That's pretty good!
« Last Edit: November 27, 2022, 05:53:00 am by DavidAlfa »
Hantek DSO2x1x            Drive        FAQ          DON'T BUY HANTEK! (Aka HALF-MADE)
Stm32 Soldering FW      Forum      Github      Donate
 
The following users thanked this post: nexus

Offline nexusTopic starter

  • Regular Contributor
  • *
  • Posts: 194
  • Country: us
Re: PIC16F1946 - Hardware SPI timing issues?
« Reply #43 on: November 27, 2022, 06:08:20 am »
Ensure to enable optimizations, O2 is free and will reduce the memory usage a lot.

Appreciate this tip! I had no idea that there were different levels of compiler optimization with the free version of XC8.

I see that there are different options that have different tradeoffs in size vs speed.
Can optimization actually increase speed/efficiency of code? Also, is it possible to "break" code with optimization that might otherwise work without it?

Thank you! Yup, I am doing my masters in electrical now, but practically all of my electrical/computer science knowledge is self taught.
It all started with nixie tubes; from there I dabbled with embedded design, power electronics, and down the rabbit hole I went...
 

Offline DavidAlfa

  • Super Contributor
  • ***
  • Posts: 5890
  • Country: es
Re: PIC16F1946 - Hardware SPI timing issues?
« Reply #44 on: November 27, 2022, 07:08:25 am »
It could break some things if not properly programmed, like interrupts writing variables not declared as volatile or for/while loops doing nothing aka simple delays (Inserting a nop in the loop would fix it, but also need to calibrate the delay).
Overall optimizations are great, both for speed and memory usage.
Try it, if you have any issues, I could review your code searching for non optimization-friendly stuff, pics are really simple and It would be easy to spot.
Hantek DSO2x1x            Drive        FAQ          DON'T BUY HANTEK! (Aka HALF-MADE)
Stm32 Soldering FW      Forum      Github      Donate
 

Offline nexusTopic starter

  • Regular Contributor
  • *
  • Posts: 194
  • Country: us
Re: PIC16F1946 - Hardware SPI timing issues?
« Reply #45 on: November 27, 2022, 07:32:00 am »
Understood. I did select optimization level 3, which is described in MPLAB as "Optimize yet more favoring speed (superset of O2)." This one appealed to me the most especially since I have a big timer interrupt that needs to run quickly to handle the rotary encoder and display.

Code: [Select]
Memory Summary:
    Program space        used  1D7Ch (  7548) of  2000h words   ( 92.1%)
    Data space           used   1D3h (   467) of   200h bytes   ( 91.2%)
    EEPROM space         used     0h (     0) of   100h bytes   (  0.0%)
    Configuration bits   used     2h (     2) of     2h words   (100.0%)
    ID Location space    used     4h (     4) of     4h bytes   (100.0%)

Shrunk the program and data space by around 8% and seems to run on the hardware just fine.

Think I might have put more effort into this unit than the OEM did in their production power supply.
 

Offline NorthGuy

  • Super Contributor
  • ***
  • Posts: 3138
  • Country: ca
Re: PIC16F1946 - Hardware SPI timing issues?
« Reply #46 on: November 27, 2022, 04:31:17 pm »
Finally, I think I've reached the finish line on this project.

Congratulations! Great project!
 
The following users thanked this post: nexus

Offline nexusTopic starter

  • Regular Contributor
  • *
  • Posts: 194
  • Country: us
Re: PIC16F1946 - Hardware SPI timing issues?
« Reply #47 on: November 27, 2022, 06:03:29 pm »
Thank you!

It will be open source soon, so it could be a useful point of reference for a generic LED driver module for others.
 

Offline Proto

  • Contributor
  • Posts: 33
  • Country: us
Re: PIC16F1946 - Hardware SPI timing issues?
« Reply #48 on: November 29, 2022, 10:11:43 pm »
I did not see anyone mention Microchip Code Configurator (MCC). I started a PIC project a few years ago after a long hiatus and grumbled that Microchip did not appear to have many code examples compared to the TI MSP430 I had used more recently. This all changed when I fired up MCC. The PIC16F15324 part I used allows on chip peripherals to be mapped to almost any port pin through a well-designed GUI. The GUI extends to picking peripherals and lets you set them up without necessarily looking at the datasheet.  MCC also reminds you to set up dependent peripherals like the TIMER1 for the Compar/Cpture subsystem. Now you press generate and you get initialization, general usage API's and interrupt functions created for you in C code, all neatly organized by peripheral name with source and hex file extensions. Its like having another programmer on your team writing your driver API's for you. Then you can modify them for your task while you also expand main.c for program flow. Is anybody using MCC?  A mix of code examples can have conflicting setup requirements when put together while MCC does a very good job of keeping all the peripherals happy.
« Last Edit: November 30, 2022, 04:24:26 am by Proto »
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf