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 CCS Technical Support

Time life battery 18F66K22 COMPILER 5.078

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



Joined: 22 Mar 2012
Posts: 70
Location: France (Paris)

View user's profile Send private message

Time life battery 18F66K22 COMPILER 5.078
PostPosted: Sat Jan 11, 2020 10:34 am     Reply with quote

Hello
I am looking to create a system that should allow me to manage the start / stop of a module to have a great autonomy. In ON mode the module consumes 5 ma vdd = 3 Vdc. The PIC is an 18F66K22. The first attempts with a first program allow me to obtain a result; 60sec sleep, 1sec ON, current 8 uA 3Vdc in sleep mode. For this project, I must use an ADXL345. The ADXL345 program alone works very well. In summary, separately both programs work well.
I want to start the first program (timer) which after 60 sec of sleep will go into On mode for 10 sec. During these 10 sec ADXL345 must
run the outdoor module for a few seconds. Here are the main parts of the final program which are not working properly. I use Hyperterminal and 2 LEDs to follow the functioning of the final program. I take advice and thank you in advance.
Code:

while(true)
  {
   accel = mesure_accel();   //OK                             
   add_value_double (&buff_accel, accel);
   delta_accel = abs( get_max_double(&buff_accel) - get_min_double(&buff_accel));
   level_median = get_median_level (&buff_level); //Trie et affiche le résultat
   //output_low(pin_G0);
  {
   sleep_for_x_seconds(5);// 10=20";40=81";30=60";25=50"
   output_high(pin_G0);   // Turn on LED 2 to show end of sleep.
   delay_ms(3000);//1000 1500
   //reset_cpu();
  }

//While(1)
//////////////////////////////////////////
resultat = sqrt(xg*xg+yg*yg+zg*zg);   

If (resultat>=1.0)
  {
   fprintf(test,"resultat = %f\n\r",resultat);
   fprintf(test," xg  = %f\n\r",xg );   
   fprintf(test," yg  = %f\n\r",yg ); 
   fprintf(test," zg  = %f\n\r",zg );
   output_high(pin_G0); // led test
   output_high(pin_E1); // power external module
   delay_ms(5000);//5000
  }   
else
  {
   output_low(pin_G0);
   output_low(pin_E1);
   //delay_ms(5000);//5000
   //reset_cpu(); 
  }

//reset_cpu(); 
return resultat;
}
Ttelmah



Joined: 11 Mar 2010
Posts: 19513

View user's profile Send private message

PostPosted: Sat Jan 11, 2020 11:19 am     Reply with quote

So, you are running off what supply voltage?.
Internal Vreg disabled?.
What clock rate?.
What is happening wrong?.
Is the ADXL set to switch to low power mode?.

There are a huge amount of functions in what you post that we don't
know what they do, or are meant to do.
Cogitum



Joined: 22 Mar 2012
Posts: 70
Location: France (Paris)

View user's profile Send private message

NEXT Time life battery 18F66K22 COMPILER 5.078
PostPosted: Sun Jan 12, 2020 12:41 am     Reply with quote

HI Ttelmah thank for your answer.
I do not use Internal Vreg disabled
Clock is 20 Mhz (xtal) and 32Khz
I tested 2 programs 1 to manage the ON / OFF the other for ADXL. Separately they work very well. The on / off program controls the supply of a BLE module
in 3 volts (I made an interface with 2 transitors for that). My goal is to combine the 2 programs. the ON / OFF program must integrate the ADXL program. adxl
must control on a movement the ON / OFF of the BLE module. Ex: 50sec sleep (off) then 10sec ON if during these 10 sec ADXL moves it puts the BLE module ON then goes to sleep.Normally I can follow on hyperterminal the X, Y, Z values of ADXL. Currently by combining the 2 programs it does not display any of the values. Embarassed
Ttelmah



Joined: 11 Mar 2010
Posts: 19513

View user's profile Send private message

PostPosted: Sun Jan 12, 2020 1:23 am     Reply with quote

If you are running off 3v, the ENVREG pin should be tied to GND to disable
the Vreg. You still need a 0.1uF capacitor to the Vcap pin, but not the 10uF
normally needed here.
Now problem is you don't show what so many parts of your program actually
do, so it is really impossible to know what isn't working.
You need to show us more to have any hope of getting help.
Cogitum



Joined: 22 Mar 2012
Posts: 70
Location: France (Paris)

View user's profile Send private message

PostPosted: Sun Jan 12, 2020 1:50 am     Reply with quote

The previous listing is the end of adxl.h
Main program:
Code:

#include "buffer.h"         // Buffer de 127 char sans médiane
#include "buffer_level.h"   // Buffer de 7 int pour accelero
#include "buffer_double.h"  // Buffer de 150 double
#include "ACCEL_ADXL365.h"



int8 sleep_timer = 0;

#define interrupt_enabled(x)  !!(*make8(x,1) & make8(x,0))
//-------------------------------------------
#byte T1CON = getenv("SFR:T1CON")
#bit  TMR1ON = T1CON.0
#byte TMR1H = getenv("SFR:TMR1H")
#byte TMR1L = getenv("SFR:TMR1L")

#define timer1_start() TMR1ON = 1;
#define timer1_stop() TMR1ON = 0;

// When Timer1 rolls over from 0xFFFF to 0x0000,
// this interrupt routine will be executed.
#int_timer1
void timer1_isr(void)
{
if(sleep_timer)
  {
   sleep_timer--;   
   timer1_stop();
   bit_set(TMR1H, 7);  // Set Timer1 MSB to 0x80   
   timer1_start();
  }

}

//-------------------------------------------
// Sleep for the specified time of 1 to 255 seconds,
// Note: The PIC will actually wake-up once per second
// briefly, and check the remaining time.

void sleep_for_x_seconds(int8 seconds)
{
int8 global_interrupts_enabled;

sleep_timer = seconds;  // Load sleep count into global variable

// Preset Timer1 so it will roll over in 1 second.
timer1_stop();
set_timer1(32768);   
timer1_start();

if(interrupt_enabled(GLOBAL))
   global_interrupts_enabled = TRUE;

clear_interrupt(INT_TIMER1);
enable_interrupts(INT_TIMER1);
enable_interrupts(GLOBAL);

// Wait in this loop until the desired delay in seconds is done.
while(sleep_timer)
  {
   sleep();
  }

// We're done, so disable Timer1 interrupts.
disable_interrupts(INT_TIMER1);

// If global interrupts were disabled outside of
// of this routine, then disable them before we exit.
if(global_interrupts_enabled == FALSE)
   disable_interrupts(GLOBAL);

}

Code:

/*
+---------------------------------------------+
| Variables                                   |
+---------------------------------------------+
*/

Buffer_level buff_level;
Buffer_double buff_accel,buff_mediane,buff_detection;

int level_median;
double delta_accel;

Code:

/*
+---------------------------------------------+
|Prototypes  de Fonctions                     |
+---------------------------------------------+
*/

unsigned long cmd_adc(char cmd);
unsigned int cmd_prom(char coef_num);
double mesure_accel();


void main()
{
// Start the Timer1 oscillator.   
// Allow 5 seconds for it to start.
//setup_timer_1(T1_EXTERNAL | T1_ENABLE_T1OSC   | T1_DIV_BY_1);
setup_timer_1(T1_EXTERNAL|T1_DIV_BY_1|0x8);
//setup_timer_1(T1_EXTERNAL|T1_DIV_BY_1);
delay_ms(1000);//1000
 
////////////////////////////////////
// Initialisation
////////////////////////////////////
 
init_buffer_level (&buff_level);
// Initialisation buffer
init_buffer_double (&buff_accel,50);                           
init_buffer_double (&buff_mediane,10);                         
init_buffer_double (&buff_detection,125);
 

   fprintf(test,"+-------------------+\r\n");
   fprintf(test,"|ACCEL BLE 11/01/20|\r\n");
   fprintf(test,"+-------------------+\r\n");
   delay_ms(2000);
//!  output_high(pin_G0);
//!  delay_ms(2000);
//!  output_low(pin_G0);
//!
//output_high(pin_G0);
sleep_for_x_seconds(10);// 10=20";40=81";30=60";25=50"
output_high(pin_G0);   // Turn on LED 2 to show end of sleep.

//delay_ms(10000);//1000 1500
//reset_cpu();


// Remplissage du buffer acceleration de Buffer_double
DOUBLE accel;
fprintf (test, "remplissage du buffer Acceleration \r\n");// OK
//output_high(pin_G0);//ok
while (buff_accel._is_full!=1)
{
accel = mesure_accel();   
add_value_double (&buff_accel, accel);
}
//output_high(pin_G0);//pas ok
fprintf (test,"Start Processus \r\n");//OK
 
//
  while(true)
   {
 accel = mesure_accel();     // fonctionne                                                                                           
 add_value_double (&buff_accel, accel);
 delta_accel = abs( get_max_double(&buff_accel)-get_min_double(&buff_accel));
 level_median = get_median_level (&buff_level); //Trie et affiche le résultat
 //output_low(pin_G0);

//While(1)
   
   } // fin while

}
Cogitum



Joined: 22 Mar 2012
Posts: 70
Location: France (Paris)

View user's profile Send private message

PostPosted: Sun Jan 12, 2020 1:53 am     Reply with quote

END og ADXL.h
§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§!
Code:

xg  = x*0.0078;    // 13 bits > 32/8192                                 
yg  = y*0.0078;                 
zg  = z*0.0078;                                                   
resultat = sqrt(xg*xg+yg*yg+zg*zg);   

 If (resultat>=1.0)
{
  fprintf(test,"resultat = %f\n\r",resultat);
   fprintf(test," xg  = %f\n\r",xg );   
    fprintf(test," yg  = %f\n\r",yg ); 
     fprintf(test," zg  = %f\n\r",zg );
output_high(pin_G0); // led test
output_high(pin_E1); // power external module
delay_ms(5000);//5000
 
}   
else
{
output_low(pin_G0);// test
output_low(pin_E1);// On/off external module
//delay_ms(5000);//5000
//reset_cpu(); 
}
//reset_cpu(); 
return resultat;
}
Ttelmah



Joined: 11 Mar 2010
Posts: 19513

View user's profile Send private message

PostPosted: Sun Jan 12, 2020 2:14 am     Reply with quote

Do you really need 5 seconds after power on before using the module?.
Most things take a fraction of a second.

It still does not give us all the 'bits'. However one thing leaps out. Nothing
will set global_interrupts_enabled to FALSE. Result you are going to get
interrupts enabled when you don't want them to be....

You need:
int8 global_interrupts_enabled=FALSE;

To make it start as FALSE. Otherwise once it has been set to 'TRUE',
it is likely to remain TRUE.
Cogitum



Joined: 22 Mar 2012
Posts: 70
Location: France (Paris)

View user's profile Send private message

PostPosted: Sun Jan 12, 2020 2:25 am     Reply with quote

No i do not need 5 sec that was just for example.
Code:

#include <18F66K22.h> //
#include <stdlib.h>     
#include <string.h>
#include <math.h>   
 
#use delay(crystal=20MHz)
#use rs232(baud=115200,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8,stream=test)
#use rs232(baud=115200,parity=N,xmit=PIN_G1,rcv=PIN_G2,bits=8,stream=debug)
#use i2c(Master,Fast=200000,sda=PIN_D5,scl=PIN_D6)  //  18F66K22

#include "buffer.h"         // Buffer de 127 char sans médiane
#include "buffer_level.h"   // Buffer de 7 int pour accelero
#include "buffer_double.h"  // Buffer de 150 double
#include "ACCEL_ADXL365.h"
=============================
// DEFINE ACCEL ADXL
#define ACCEL_WRITE_ADDR   0XA6  // suivant cablage !
#define ACCEL_READ_ADDR    0XA7                       
#define ACCEL_DATA_ADDR    0x32                                     
#define ACCEL_PWRCTRL_ADDR 0x2d                                   
#define ACCEL_MEASURE_MODE 0x08                                                                   
#define BP PIN_B0     
//_____ M A C R O S
#define ADDR_W       0xEE // Module address write mode     suivant cablage             
#define ADDR_R       0xEF // Module address read mode
#define CMD_RESET    0x1E // ADC reset command                                     
#define CMD_ADC_READ 0x00 // ADC read command
#define CMD_ADC_CONV 0x40 // ADC conversion command                   
#define CMD_ADC_D1   0x00 // ADC D1 conversion Pression
#define CMD_ADC_D2   0x10 // ADC D2 conversion TEMPERATURE
#define CMD_ADC_256  0x00 // ADC OSR=256
#define CMD_ADC_512  0x02 // ADC OSR=512
#define CMD_ADC_1024 0x04 // ADC OSR=1024
#define CMD_ADC_2048 0x06 // ADC OSR=2048                       
#define CMD_ADC_4096 0x08 // ADC OSR=4096
#define CMD_PROM_RD  0xA0 // Prom read command 


signed int accel_data[6];   
signed int x,y,z;   
double xg,yg,zg;     

//********************************************************
//! @brief preform adc conversion
//! @return 24bit result
//********************************************************

unsigned long cmd_adc(char cmd)
{
unsigned  int ret;
unsigned  long temp;
 
i2c_start();
i2c_write(ADDR_W);
i2c_write(CMD_ADC_CONV+cmd); // send conversion command
i2c_stop();
switch (cmd & 0x0f)          // wait necessary conversion time
{
case CMD_ADC_256 :  delay_us(900); break;
case CMD_ADC_512 :  delay_ms(3);   break;
case CMD_ADC_1024:  delay_ms(4);   break;
case CMD_ADC_2048:  delay_ms(6);   break;
case CMD_ADC_4096:  delay_ms(10);  break;
}
i2c_start();
i2C_write(ADDR_W);
i2c_write(CMD_ADC_READ);
i2c_stop();

i2c_start();
i2C_write(ADDR_R);
ret = i2c_read();  //  read MSB and acknowledge
temp= 65536*ret;   
ret = i2c_read();  // read byte and acknowledge
temp=temp+256*ret;
ret = i2c_read(0); // read LSB and not acknowledge
temp= temp+ret;     
i2c_stop();        // send stop condition
return temp;
}

//********************************************************
//! @brief Read calibration coefficients
//! @return coefficient
//********************************************************
unsigned int cmd_prom(char coef_num)
{                                                                                     
unsigned int ret;
unsigned int rC=0;
i2c_start();
i2C_write(ADDR_W);
i2c_write(CMD_PROM_RD+coef_num*2); // send PROM READ command
i2c_stop();
                                                       
i2c_start();
i2c_write(ADDR_R);
ret = i2c_read();   // read MSB and acknowledge
rC=256*ret;
ret = i2c_read(0);  // read LSB and Not acknowledge
rC=rC+ret;
i2c_stop();

return (rC); //
 
}
 
                                                             
double mesure_accel()
{
double resultat;
// Tell the accelerometer to wake up
i2c_start();
i2c_write(ACCEL_WRITE_ADDR);
i2c_write(0X31);
/////i2c_write(0X0B);////+-16      init des registres (scale)                             
i2c_write(0X01);///+-4g
i2c_stop();                                   
                                 
I2C_start();                                                         
i2c_write(ACCEL_WRITE_ADDR);                           
i2c_write(ACCEL_PWRCTRL_ADDR);       
i2c_write(ACCEL_MEASURE_MODE);                                             
I2C_stop();

// Read data from the accel
i2c_start();                               
i2c_write(ACCEL_WRITE_ADDR);
i2c_write(ACCEL_DATA_ADDR);
i2c_start();
i2c_write(ACCEL_READ_ADDR);                     
accel_data[0] = i2c_read(); //x0                   
accel_data[1] = i2c_read(); //x1           
accel_data[2] = i2c_read(); //y0
accel_data[3] = i2c_read(); //y1
accel_data[4] = i2c_read(); //z0                     
accel_data[5] = i2c_read(0); // z1, NACK on last read
i2c_stop();
                                                                 
//////////concatenation adxl345///////////// 
                       
x=MAKE16(accel_data[1],accel_data[0]);
y=MAKE16(accel_data[3],accel_data[2]);           
z=MAKE16(accel_data[5],accel_data[4]);
Ttelmah



Joined: 11 Mar 2010
Posts: 19513

View user's profile Send private message

PostPosted: Sun Jan 12, 2020 3:00 am     Reply with quote

One big issue you may not realise. Your chip does not support 'double'. On the PIC16 and 18, double codes as a single precision float. It only gives double precision on the DsPIC's.

Same applies in several other places. Though you say the code worked.
For instance:
Code:

//Unsigned long on a PIC18, is only a 16bit value yet you talk
//about returning 24bits....
unsigned long cmd_adc(char cmd)
{
unsigned  int ret;
//same issue here with the temporary variable
unsigned  long temp;
 
i2c_start();
i2c_write(ADDR_W);
i2c_write(CMD_ADC_CONV+cmd); // send conversion command
i2c_stop();
switch (cmd & 0x0f)          // wait necessary conversion time
{
case CMD_ADC_256 :  delay_us(900); break;
case CMD_ADC_512 :  delay_ms(3);   break;
case CMD_ADC_1024:  delay_ms(4);   break;
case CMD_ADC_2048:  delay_ms(6);   break;
case CMD_ADC_4096:  delay_ms(10);  break;
}
i2c_start();
i2C_write(ADDR_W);
i2c_write(CMD_ADC_READ);
i2c_stop();

i2c_start();
i2C_write(ADDR_R);
ret = i2c_read();  //  read MSB and acknowledge

//Won't work. 65536*RET will overflow the 16bit variable
temp= 65536*ret;   
ret = i2c_read();  // read byte and acknowledge
temp=temp+256*ret;
ret = i2c_read(0); // read LSB and not acknowledge
temp= temp+ret;     
i2c_stop();        // send stop condition
return temp;
}

So in fact your code here is only reading the low 16bits of the value....

Get out of the habit of using keywords like 'long'. Instead use
explicit sizes. Code your variable and function here as unsigned int32.

You call lots of as yet unposted functions referring to 'double', but since
the type doesn't actually exist, these are almost certainly not doing what
you expect.
Cogitum



Joined: 22 Mar 2012
Posts: 70
Location: France (Paris)

View user's profile Send private message

PostPosted: Sun Jan 12, 2020 4:25 am     Reply with quote

Thank a lot Ttelmah for your advice.
what distorts thinking is that software works properly separately.
I will put your recommendations into practice.
Perhaps the best solution would have been to use only
ADXL to turn the BLE module ON / OFF. ADXL becoming the operations manager. As soon as we move him while he sleeps he wakes up
BLE ON / OFF. Yours, I will keep you posted on the evolution because I have very little time to finish.
Ttelmah



Joined: 11 Mar 2010
Posts: 19513

View user's profile Send private message

PostPosted: Sun Jan 12, 2020 6:29 am     Reply with quote

If it doesn't display any values, my suspicion is that the ADXL, is not being
woken up. You do understand it'll go to sleep if not accessed?. If you are
switching off it's supply (which you seem to suggest), then it needs to
be re-initialised/configured before it'll work.

The code is so disjointed, and posted in so many incomplete 'bits' that it is
impossible to actually work out how things are meant to occur.

Sequence what you want it to do, then look at how this compares with what
your code actually does.
So if you are turning off the chip, something like:

a) Turn chip on.
Initialise.
Wait to stabilise.
b) Reading as existing code.
Loop to 'b' till time expires.
Turn off chip.
Now sleep.
Loop to 'a' when sleep complete.

You are presumably getting away with the use of int16's, since movements
are small enough to fit in int16 values. Will only give problems with
larger accelerations.
Cogitum



Joined: 22 Mar 2012
Posts: 70
Location: France (Paris)

View user's profile Send private message

PostPosted: Sun Jan 19, 2020 10:20 am     Reply with quote

Thank Ttelmah Very soory for my answer delay.
One problem was this fuse ; #FUSES SOSC_HIGH
The oscillators are running now.

I have another priority for now and i need to post the problem.

My best regards
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