CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

Help. As I stabilize last digit with max7219

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
rosiley



Joined: 29 May 2014
Posts: 18
Location: Brasil

View user's profile Send private message

Help. As I stabilize last digit with max7219
PostPosted: Tue Feb 28, 2017 7:34 am     Reply with quote

Hi everyone, I have a problem here, my code is works normally, but the last digit does not stabilize it oscillates +/- 5 mv. I am using 18f4553 configured for 12 bits with max7219.

I used this code.

Code:

//=========================Variaveis do MAX7219 veja Datasheet================\\
#define NO_OP                       0x00  // Used when cascading max7221s

#define DIGIT_0                     0x01  // Digit 0 register
#define DIGIT_1                     0x02  // Digit 1 register
#define DIGIT_2                     0x03  // Digit 2 register
#define DIGIT_3                     0x04  // Digit 3 register
#define DIGIT_4                     0x05  // Digit 4 register
#define DIGIT_5                     0x06  // Digit 5 register
#define DIGIT_6                     0x07  // Digit 6 register
#define DIGIT_7                     0x08  // Digit 7 register

#define DECODE_MODE                 0x09  // Decode mode register
#define INTENSITY                   0x0A  // Intensity register
#define SCAN_LIMIT                  0x0B  // Scan-limit register
#define SHUT_DOWN                   0x0C  // Shutdown register
#define DISPLAY_TEST                0x0F  // Display-test register

// Shutdown register
#define SHUTDOWN_MODE               0x00  // Shutdown mode
#define NORMAL_MODE                 0x01  // Normal mode

// Decode-mode register
#define NO_DECODE_DIGITS_7_0        0x00  // No decode for digits 7-0
#define CODE_B_DECODE_DIGIT_0       0x01  // Code B decode for digit 0
#define CODE_B_DECODE_DIGITS_3_0    0x0F  // Code B decode for digits 3-0
#define CODE_B_DECODE_DIGITS_7_0    0xFF  // Code B decode for digits 7-0

// Intensity register
#define DUTY_CYCLE_1                0x00  // Intensity min
#define DUTY_CYCLE_2                0x01
#define DUTY_CYCLE_3                0x02
#define DUTY_CYCLE_4                0x03
#define DUTY_CYCLE_5                0x04
#define DUTY_CYCLE_6                0x05
#define DUTY_CYCLE_7                0x06
#define DUTY_CYCLE_8                0x07
#define DUTY_CYCLE_9                0x08
#define DUTY_CYCLE_10               0x09
#define DUTY_CYCLE_11               0x0A
#define DUTY_CYCLE_12               0x0B
#define DUTY_CYCLE_13               0x0C
#define DUTY_CYCLE_14               0x0D
#define DUTY_CYCLE_15               0x0E
#define DUTY_CYCLE_16               0x0F  // Intensity full

// Scan-limit register
#define DISPLAY_DIGIT_0             0x00  // Display digit 0
#define DISPLAY_DIGITS_01           0x01  // Display digits 0 1
#define DISPLAY_DIGITS_012          0x02  // Display digits 0 1 2
#define DISPLAY_DIGITS_0123         0x03  // Display digits 0 1 2 3
#define DISPLAY_DIGITS_01234        0x04  // Display digits 0 1 2 3 4
#define DISPLAY_DIGITS_012345       0x05  // Display digits 0 1 2 3 4 5
#define DISPLAY_DIGITS_0123456      0x06  // Display digits 0 1 2 3 4 5 6
#define DISPLAY_DIGITS_01234567     0x07  // Display digits 0 1 2 3 4 5 6 7

// Display-test register
#define NORMAL_OPERATION            0x00  // Operação Normal
#define DISPLAY_TEST_MODE           0x01  // Display-test mode, todos leds ON

void SPI_MAX7219(unsigned char dato);     /* Declaramos a função que nos permitirá
                                          /  enviar os dados de escrita no MAX*/
void Comandos_MAX7219(unsigned char direc,unsigned char dato ); /* Função exclusiva
                                          para enviar comandos */
void Init_MAX7219(unsigned char decode);// 0xFF o 0x00 (Ativa ou desativa o decodificador)

void Write_MAX7219(unsigned char num,unsigned char direc,unsigned char dato );

Void SPI_MAX7219( unsigned  char dato){
   int con;
     for(con=8;con>0;con--)
     {
         output_low(MAX_CLK);
         if(bit_test(dato,con-1)==0)
            output_low(MAX_DIN);           
         else
            output_high(MAX_DIN);           
            output_high(MAX_CLK);
      }
}
void Comandos_MAX7219(unsigned char direc,unsigned char dato )
{
   unsigned char cont;
   output_low(MAX_LOAD); 
   for(cont=0; cont<N_MAX;cont++)
{
   SPI_MAX7219(direc);
   SPI_MAX7219(dato);
   }
   output_high(MAX_LOAD);
}
void Init_MAX7219(unsigned char decode)
{
   output_low(MAX_DIN);
   output_low(MAX_CLK);
   output_high(MAX_LOAD);
   
   Comandos_MAX7219(0x09,decode);// Desativamos o modo DECODER 
   Comandos_MAX7219(0x0A,0x01);  // Ajustamos o PWM 21/32
   Comandos_MAX7219(0x0c,0x00);  // Desativamos o MAX
   
   Comandos_MAX7219(0x0B,0x05);  // Ajustamos o Scaneo que será de DIG0 a DIG5
   Comandos_MAX7219(0x0c,0x01);  // Desativamos o MAX
   Comandos_MAX7219(0x0F,0x00);  // Desativamos o TEST
   Comandos_MAX7219(0x0C,0x01);  // Ativamos o MAX
}
void Write_MAX7219(unsigned char num,unsigned char direc,unsigned char dato )
{
    unsigned char MAX_DATO[10]={0,0,0,0,0,0,0,0,0,0}; 
    unsigned char rep;
    unsigned char cont;
    rep = N_MAX*2;
    MAX_DATO[num*2-1]=direc;
    MAX_DATO[num*2-2]=dato;
    output_low(MAX_LOAD);
    for(cont=rep; cont>0;cont--)
    {
      SPI_MAX7219(MAX_DATO[cont-1]);
    }
    output_high(MAX_LOAD);
}




Code:

#include "UDAD_main.h"
#include "MAX7219.C"
/*==============================================================================
                        CANAL RA0 PIN 2 ANALOGUE INPUT 1 - lblsensor 1
==============================================================================*/
void ADCinput0()                 
{
   set_adc_channel(0);
   delay_us(10);
   ADinput0 = READ_ADC();       
   AD0 = (ADinput0 * 5000) /4095;
   printf("1@1%04lu",AD0);   //Envia dados de conversão A/D para exibir tensão
   printf("7");
   
   Write_MAX7219(1,1, 0b0101010);            //milhar
   Write_MAX7219(1,2, AD0/1000| 0b10000000); //centena
   Write_MAX7219(1,3,(AD0%1000)/100);        //dezena
   Write_MAX7219(1,4,(AD0%100)/10);          //unidade
   Write_MAX7219(1,5, AD0%10);
   Write_MAX7219(1,6, AD0%1);
   
}


Code:


void main()
{

   setup_adc_ports(AN0_TO_AN9|VSS_VDD);
   setup_adc(ADC_CLOCK_DIV_32);
   enable_interrupts(GLOBAL);
   enable_interrupts(INT_RDA);
   enable_interrupts(INT_TIMER0);   
   setup_psp(PSP_DISABLED);
   setup_wdt(WDT_OFF);
   setup_timer_0(RTCC_INTERNAL | RTCC_DIV_256 | RTCC_8_BIT);
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DISABLED,0,1);
   setup_timer_3(T3_DISABLED|T3_DIV_BY_1);
   setup_comparator(NC_NC_NC_NC);
   setup_vref(FALSE);
   set_timer0(61);

   output_D(0X00);
   backlight = input_state(PIN_D7);
   
   /*===========================================================================
                        HABILITA O DRIVER MAX7219
   ===========================================================================*/   
   //Decode Mode Enable
   Init_MAX7219(0xFF);
   delay_ms(1000); 
   /*===========================================================================
                        LOOP PRINCIPAL
   ===========================================================================*/     
   while (true)
   
   {
         /*===================DIRETIVAS ENTRADAS ANALÓGICAS===================*/
            ADCinput0();
Ttelmah



Joined: 11 Mar 2010
Posts: 19451

View user's profile Send private message

PostPosted: Tue Feb 28, 2017 8:39 am     Reply with quote

Honestly, VSS_VDD.

You are unlikely to be able to get better than 8bit useable resolution using the supply as your reference. Every time the PIC does something (particularly things like switching displays drawing some current), the supply _will_ ripple. Even the best regulator takes time to correct.
To honestly get a really useable 12bit resolution requires really careful design of all the circuitry involved, a good reference, and good PCB layout.
rosiley



Joined: 29 May 2014
Posts: 18
Location: Brasil

View user's profile Send private message

PostPosted: Tue Feb 28, 2017 8:54 am     Reply with quote

Okay, but my code reads a value that at the moment is varying from 1,045 mv to 1,048 on the last digit and the source is well stabilized, not showing any variation right now. The values ​​of thousand, hundred and ten are ok, only the units are that they vary.
Mike Walne



Joined: 19 Feb 2004
Posts: 1785
Location: Boston Spa UK

View user's profile Send private message

PostPosted: Tue Feb 28, 2017 9:06 am     Reply with quote

rosiley wrote:
Okay, but my code reads a value that at the moment is varying from 1,045 mv to 1,048 on the last digit and the source is well stabilized, not showing any variation right now. The values ​​of thousand, hundred and ten are ok, only the units are that they vary.
You're being asked the question:-

How do you KNOW that BOTH the source and the reference are sufficiently well stabilised?

Mike
rosiley



Joined: 29 May 2014
Posts: 18
Location: Brasil

View user's profile Send private message

PostPosted: Tue Feb 28, 2017 9:13 am     Reply with quote

I have here a multimeter and it show me a value around 5.01 volts.

At this moment I'm switching the reference source to an adjustable one to see what happens.
Ttelmah



Joined: 11 Mar 2010
Posts: 19451

View user's profile Send private message

PostPosted: Tue Feb 28, 2017 9:31 am     Reply with quote

Wrong answer I'm afraid.... Smile

A multimeter _integrates_ the signal. Most (unless you pay a lot of money for high speed meters from somebody like Fluke), will not see signals above a very few Hz. Most cheaper ones have update rates of only about 4Hz. Problem is that the noise you are likely to have is high frequency.
Also you say '5.01', A 12bit ADC, running off 5v will have a resolution of 1.2mV/ step. You need at least 3 decimal places after the '5', to see this type of signal.

Just switching the source, won't help unless the source you have is a really high stability type. and the ground layout around the circuit is good
Mike Walne



Joined: 19 Feb 2004
Posts: 1785
Location: Boston Spa UK

View user's profile Send private message

PostPosted: Tue Feb 28, 2017 9:37 am     Reply with quote

rosiley wrote:
I have here a multimeter and it show me a value around 5.01 volts.

At this moment I'm switching the reference source to an adjustable one to see what happens.
Like Mr T. says, there's more to it than your DVM can show.

I'd be having a look around with an AC coupled scope for starters.
Could be very revealing.

Mike

I see Mr T. got in as I typed, adds to my comments.
rosiley



Joined: 29 May 2014
Posts: 18
Location: Brasil

View user's profile Send private message

PostPosted: Tue Feb 28, 2017 9:43 am     Reply with quote

Testing here I verified that my reference was not good, I changed it and I improved the code now I already have a variation around 1 mv that is acceptable for the proposed circuit. I will improve the layout of the circuit because it is mounted on a prototype board without much filtering.
rosiley



Joined: 29 May 2014
Posts: 18
Location: Brasil

View user's profile Send private message

PostPosted: Tue Feb 28, 2017 9:47 am     Reply with quote

My problem was really in the reference voltage, I'm going to use a tl431 to make the reference and I think I should solve my problem. And in the final circuit I will use precision resistor so everything is the way I want it.
Ttelmah



Joined: 11 Mar 2010
Posts: 19451

View user's profile Send private message

PostPosted: Tue Feb 28, 2017 9:55 am     Reply with quote

Good.

Now as a comment, to improve things (but you do need to be starting with something worth improving...), look at averaging.

One 'classic' is Olympic averaging:
Code:

   int16 sum,temp;
   int16 max,min;
   int8 ctr;
   max=0;
   min=4096;
   sum=0;
   for (ctr=0;ctr<6;ctr++)
   {
       delay_us(5);
       temp=read_adc();
       sum+=temp; //add six
       if (temp>max) //record if this is a new 'max' value
          max=temp;
       if (temp<min) //same if this is a new 'min' value
          min=temp;
   }
   sum-=max;
   sum-=min; //now subtract the max and min
   //now if you use sum/4 you will get a very good average


You get the average of the four 'middle' readings. This is the basis of the scoring system used in Olympic events where they have a jury of (say) five members, and reject the highest and lowest scores. It's a very powerful way of quite quickly getting an average, and rejecting 'extreme' values. Using a count that requires a 'binary' division at the end (6, or 10 readings say), makes the code very fast, since on an integer /4 /8 etc., can be done by simple rotation. Smile
Ttelmah



Joined: 11 Mar 2010
Posts: 19451

View user's profile Send private message

PostPosted: Tue Feb 28, 2017 9:58 am     Reply with quote

A TL431 is not really a precision reference. For a 12bit ADC, you need something like a X60008-41 (4.096v reference).

Different 'class' I'm afraid.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group