| 
	
	|  |  |  
	
		| 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;
 }
 | 
 |  |  
		|  |  
		| Ttelmah 
 
 
 Joined: 11 Mar 2010
 Posts: 19966
 
 
 
			    
 
 | 
			
				|  |  
				|  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.
 |  |  
		|  |  
		| 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.
  |  |  
		|  |  
		| Ttelmah 
 
 
 Joined: 11 Mar 2010
 Posts: 19966
 
 
 
			    
 
 | 
			
				|  |  
				|  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.
 |  |  
		|  |  
		| 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
 
 }
 | 
 |  |  
		|  |  
		| 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;
 }
 | 
 |  |  
		|  |  
		| Ttelmah 
 
 
 Joined: 11 Mar 2010
 Posts: 19966
 
 
 
			    
 
 | 
			
				|  |  
				|  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.
 |  |  
		|  |  
		| 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]);
 | 
 |  |  
		|  |  
		| Ttelmah 
 
 
 Joined: 11 Mar 2010
 Posts: 19966
 
 
 
			    
 
 | 
			
				|  |  
				|  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.
 |  |  
		|  |  
		| 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.
 |  |  
		|  |  
		| Ttelmah 
 
 
 Joined: 11 Mar 2010
 Posts: 19966
 
 
 
			    
 
 | 
			
				|  |  
				|  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.
 |  |  
		|  |  
		| 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
 |  |  
		|  |  
		|  |  
  
	| 
 
 | 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
 
 |