![](templates/subSilver/images/CCSLogo.jpg) |
![CCS C Software and Maintenance Offers](templates/subSilver/images/forumAd6.jpg) |
View previous topic :: View next topic |
Author |
Message |
Cogitum
Joined: 22 Mar 2012 Posts: 70 Location: France (Paris)
|
Time life battery 18F66K22 COMPILER 5.078 |
Posted: Sat Jan 11, 2020 10:34 am |
|
|
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;
} |
|
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19378
|
|
Posted: Sat Jan 11, 2020 11:19 am |
|
|
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. |
|
![](templates/subSilver/images/spacer.gif) |
Cogitum
Joined: 22 Mar 2012 Posts: 70 Location: France (Paris)
|
NEXT Time life battery 18F66K22 COMPILER 5.078 |
Posted: Sun Jan 12, 2020 12:41 am |
|
|
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](images/smiles/icon_redface.gif) |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19378
|
|
Posted: Sun Jan 12, 2020 1:23 am |
|
|
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. |
|
![](templates/subSilver/images/spacer.gif) |
Cogitum
Joined: 22 Mar 2012 Posts: 70 Location: France (Paris)
|
|
Posted: Sun Jan 12, 2020 1:50 am |
|
|
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
} |
|
|
![](templates/subSilver/images/spacer.gif) |
Cogitum
Joined: 22 Mar 2012 Posts: 70 Location: France (Paris)
|
|
Posted: Sun Jan 12, 2020 1:53 am |
|
|
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;
} |
|
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19378
|
|
Posted: Sun Jan 12, 2020 2:14 am |
|
|
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. |
|
![](templates/subSilver/images/spacer.gif) |
Cogitum
Joined: 22 Mar 2012 Posts: 70 Location: France (Paris)
|
|
Posted: Sun Jan 12, 2020 2:25 am |
|
|
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]); |
|
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19378
|
|
Posted: Sun Jan 12, 2020 3:00 am |
|
|
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. |
|
![](templates/subSilver/images/spacer.gif) |
Cogitum
Joined: 22 Mar 2012 Posts: 70 Location: France (Paris)
|
|
Posted: Sun Jan 12, 2020 4:25 am |
|
|
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. |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19378
|
|
Posted: Sun Jan 12, 2020 6:29 am |
|
|
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. |
|
![](templates/subSilver/images/spacer.gif) |
Cogitum
Joined: 22 Mar 2012 Posts: 70 Location: France (Paris)
|
|
Posted: Sun Jan 19, 2020 10:20 am |
|
|
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 |
|
![](templates/subSilver/images/spacer.gif) |
|
|
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
|