Jump to content

DavidT

EstablishedMember
  • Content Count

    60
  • Joined

  • Last visited

Everything posted by DavidT

  1. I found the technique in post 1 of this link to be helpful in storing large amounts of data. In my case I strung together 10*256bytes on an 18F. http://forum.sourceboost.com/index.php?showtopic=3660 David.
  2. Hi. If you are using normal servos then they will be expecting a pulse of between 1 and 2ms every 20ms. I'd guess your two controls are aileron (or rudder) and elevator. They don't need to be operated exactly together so you can simply make servo1 go high for between 1 and 2ms then low, then do the same for servo2. Then wait about 17ms and start again. The 1-2ms is important but the 20ms timing is not. You might be able to do this with delays, or otherwise just wait for a 16bit timer to reach appropriate values before making ports high/low. If your motor control is via a commercial electronic speed control it will be expecting the same signal. So you can simply tag this on after servo1 and 2 and reduce the delay before starting the next cycle. This 'sequential' approach will work with up to 10 devices. Clearly you will need a whole bunch of logic to convert pitch and roll movements picked up by your accelerometers into servo instructions. Regards, David.
  3. Thanks. I think Pg65 of BoostC pdf in 6.91rc3 needs updating. Regards, David.
  4. I use the approach in post 7 but with reference diodes instead of zeners. These can be extremely accurate. Farnell sometimes have them in 10v although 5v and less are more common. I have 2 examples on my site. Follow the 'back' button at the foot of both pages. This will take you to a circuit description which explains how I use them. http://www.flyelectric.ukgateway.net/bal3-cct.htm http://www.flyelectric.ukgateway.net/lithtester2-cct.htm Regards, David.
  5. Thanks Reynard. I normally typedef u8 as char and 'volatile u8' seems to work. Cheers, David.
  6. Should I be able to do this? Compiler gives error (v6.90): Regards, David. typedef volatile unsigned char v8;
  7. I can't keep up :-) Thanks for the regular updates. Regards David.
  8. This seems a useful way of creating large arrays but the bug does not seem fixed in v6.89. Overlooked perhaps? Regards, David.
  9. The uitoa_dec function in this design may help you http://www.flyelectric.ukgateway.net/pic-lcd1.htm David.
  10. I'm not sure if PicKit2 does low voltage programming but it definitely does high voltage (the manual refers to a 12v Vpp). No mods are needed to the programmer. The config I gave you works perfectly on a default install of PicKit2. It is normal to link the Pic's MCLR pin to Vdd with a 10k resistor to prevent a floating input and random resets. While you are struggling, make sure nothing else is connected to the MCLR, PGD or PGC pins as extra circuitry can interfere with programming, especially the clock pin. dt.
  11. I've used the following successfully on a 16F88 (when looking up these settings in the data sheet note that Fosc uses bits 4, 1 and 0; can be confusing): #pragma DATA 0x2007, 0b11111101010000 //Config1 #pragma DATA 0x2008, 0b00 //Config2 I recall reading about a special low voltage setting which can be used to recover Pics. You'll need to troll through some of the posts: http://forum.microchip.com/tt.aspx?forumid=15 David.
  12. DavidT

    V6.85rc

    An old project would not compile. Displayed "Building..." at the bottom and nothing else. I installed it to a '685' folder and my previous version was to a '683' folder. When I looked at Settings/Options/Tools the Compiler&Link Directory field had defaulted to C:\Program Files\SourceBoost683\ I've had to change this manually to my new directory. I don't remember having to do this before. David.
  13. I time or debounce push-button presses in interrupts with this: for(i=0; i<100; i++) nop(); Regards, David.
  14. 1. Can you create a list of 'favourite' devices perhaps at the top of the Target drop down list. I'm sure most of us use a very small number of devices. 2. To maximise the size of the main editing panel, can you reduce the rows taken to display key messages at the end of the Output window. I like to see the 3 'Memory Usage Report' rows but would then like one more row that says something like "Successful but with 'x' warning messages/'y' errors". I then know whether to scroll up or not. 'Done' is redundant I think and the empty rows at the end are waste of space (empty rows higher up are OK to improve presentation). The two rows with the path are not useful to me but if they have a purpose perhaps put them slightly higher so I can adjust the window size to hide that info. Thanks, David.
  15. The comparators can make ports toggle so it's also worth switching them off. I'm normally specific with my analogue/digital config. David. ansel = 0; cm1con0.7 = 0; cm2con0.7 = 0;
  16. Yes, very much like what I have in mind. A quick test with the first suggests the compiler won't accept it though. I'll experiment a bit more tomorrow. David.
  17. Thanks, this gives me more function orientated approaches and improvements. Is there any way to use an array or bits in a variable with each representing LED ports? I would like to switch the LEDs in a loop such as below. I can go with a function if necessary; I would just prefer to avoid the code overhead it seems to impose. David. if(i=0; i<3; i++) { led_function(i,1); //Switch LEDs on via function led_array[i]=1; //Use an array? set_bit(led_variable,i); //Bits in a variable? }
  18. Hi folk, I would like switch LEDs and FETs on and off in loops. I can define them individually but then I have to specify each every time. I can also set up a function and call that (see below) but this seems to increase code size. Are there better ways please? Thanks, David. void led (char num, bit state) //Function to switch LEDs //'num' is LED number //'state' is 1=on, 0=off { if(num==1 && state==0) portc.4=0; //LED1 else if(num==1 && state==1) portc.4=1; else if(num==2 && state==0) porta.5=0; //LED2 else if(num==2 && state==1) porta.5=1; }
  19. rom char *your_array_name = { 0x01, 0x02, 0x03 }; your_array_name[1] holds 0x02. char type only, max 256bytes per array; see manual for more examples. David.
  20. I'm storing mine in multiple arrays all <0x100, usually in program memory using the rom command. One parameter in my 'font' function selects the array (eg: 1=numerals, 2=upper, 3=lower case) and the other the first offset for the character. You can see how I've done it in my Eratic F18 post. David.
  21. Setting each of the 5 log arrays to a fixed address at the start of separate ram banks (eg: @0x100, @0x200, etc) also appears to make it work. David.
  22. I've written a program to measure individual cells in a pack and display graphs on a graphic LCD. I'm using an 18F2523 and BoostC 6.81. I want to perform 96 measurement cycles and am storing these ultimately in 5 fairly large arrays (log1-5), 1 for each cell. When these arrays and the code that populates them (in main and log_highlow) are where I have them in the code below, the PIC is unstable. By this I mean it either works as expected, displays nothing, scrambles some or all characters, responds to interrupts or not, etc. Packs with different voltages yield different behaviour. When I comment the highlighted sections out and put the 'log' arrays and code in the same function (display_graph) it is stable irrespective of the voltage inputs. The Interrupts are removed so they are not the cause. Looking at other posts I see people experience problems sometimes with variables being over-written, etc. I don't know how to check for this but do believe I've narrowed down the area cause instability. I suspect the log arrays. Can anyone suggest how to proceed please? I've tried to reduce the code to what it needs to demonstrate the problem but sorry it is still so long. I suspect you only need to look at the sections marked with hashes. As a side issue the log_highlow function produces 1194 words of code which seemed a lot to me. Thanks, David. #include <system.h> //Generic device include (actual device set in Settings/Target) #include <stdlib.h> //Needed for Integer to ASCII conversion (uitoa) //Core configuration (some commented out to leave at default): #pragma DATA 0x300001, 0b1000 //Config1H: Internal oscillator with IO on RA6 and 7 #pragma DATA 0x300002, 0b11110 //Config2L: Brownout min voltage, hardware only, Powerup timer ON #pragma DATA 0x300003, 0 //Config2H: Watchdog timer DISabled #pragma DATA 0x300006, 0b10000001 //Config4L: Debug, Extended instructions and low volt pmg OFF #pragma DATA 0x30000A, 0b1100 //Config6L: Write protect Blocks 0 & 1 ENabled, 2 & 3 disabled #pragma DATA 0x30000B, 0b10000000 //Config6H: Write protect Boot and Config ENabled, EEPROM disabled //VARIABLES and DEFINITIONS ==================================================== #define data latc //Defines Latch C as 'data' for writing to LCD via Port C (8 data lines) #define status portc //Defines Port C as 'status' for reading the port #define rs porta.6 //Defines RS / RI (data/instruction) pin #define rw porta.7 //Defines R/W read write pin #define menu portb.0 //Defines Menu pushbutton (uses 'mode' flags in prgram) #define select portb.1 //Defines Select pushbutton (uses 'sel' flags in prgram) #define en portb.5 //Defines Enable pin #define cs1 portb.6 //Defines chip select 1 (left) - low to select #define cs2 portb.7 //Defines chip select 2 (right) typedef unsigned char u8; //Defines u8 as an unsigned char type (8bits) typedef signed char s8; //Defines s8 as an signed char type (8bits) typedef unsigned int i16; //Defines i16 as an unsigned short integer (16bits) typedef unsigned long u32; //Defines u32 as an unsigned long type (32bits) //############################################################################## //Program is eratic when this is here - works when in display_lcd() i16 log1[97]; //Stores measurements for cell 1 etc... i16 log2[97]; i16 log3[97]; i16 log4[97]; i16 log5[97]; //############################################################################## i16 log_high[6]; //Highest value measured for cell 1 etc i16 log_highest; //Highest value of all cells i16 log_low[6]; //Lowest for cell i16 log_lowest; //Lowest of all cells u32 adc_result[8]; //Cummulative results of AD conversions for each cell u8 graph[] = { //'Library 4' for LCD fonts 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01, //0-7 Lowest to highest graph dots 0x00, //8 Space (1 pixel) 0xFF //9 | (all vertical dots on) }; u8 graph1[] = { //'Library 5' for LCD fonts 0x3e, 0x51, 0x49, 0x45, 0x3E, 0x00, // 0 0x00, 0x04, 0x02, 0x7F, 0x00, 0x00, // 1 0x62, 0x51, 0x49, 0x49, 0x46, 0x00, // 2 0x22, 0x41, 0x49, 0x49, 0x36, 0x00, // 3 0x18, 0x14, 0x12, 0x7F, 0x10, 0x00, // 4 0x4F, 0x49, 0x49, 0x49, 0x31, 0x00, // 5 0x3E, 0x49, 0x49, 0x49, 0x32, 0x00, // 6 0x03, 0x01, 0x61, 0x19, 0x07, 0x00, // 7 0x36, 0x49, 0x49, 0x49, 0x36, 0x00, // 8 0x26, 0x49, 0x49, 0x49, 0x3E, 0x00, // 9 0x00, 0x36, 0x36, 0x00, 0x00, 0x00, // : 0x14, 0x7F, 0x14, 0x7F, 0x14, 0x00, // # 0x00, 0x00, 0x60, 0x60, 0x00, 0x00, // . 0x7F, 0x09, 0x09, 0x09, 0x7F, 0x00, // A 0x00, 0x00, 0x3F, 0x40, 0x40, 0x00, // l 0x7F, 0x02, 0x04, 0x02, 0x7F, 0x00, // M 0x46, 0x49, 0x49, 0x49, 0x31, 0x00, // S 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // Space }; i16 result; //Merges ADC high and low registers u32 convert; //Used in converting ADC values to volts u8 h_addr; //Horizontal address (0-127) - must start at 0 for each new row u8 v_addr; //Vertical address (0-7) u8 s_addr; //Scroll address (0-64) u8 mode; //Current 'Menu' selected u8 mode_min; //Smallest menu option u8 mode_max; //Largest menu option u8 sel; //Current 'Select' option u8 sel_min; //Smallest selection option u8 sel_max; //Largest selection option u8 pack_size; //Size of pack set in Mode 1; computes/displays all cells up to this number u8 pack_log; //Number of cells actually logged in Mode 2 u8 cell_num; //Individual cell (singlar) set in Mode 2; 0 represents all measured void lcd_coord(); //Sets LCD co-ordinates void lcd_font (u8 library, u8 offset); //Selects fonts from libraries and advances h_addr void lcd_write (u8 send, u8 mode); //Sends characters and commands to LCD void lcd_refresh(); //Clears LCD void adc (u8 cells); //Performs AD conversions, sums results; called by... void measure_cells (i16 iter); //Initialisation and triggering of cell measurements void volts_calc (u8 cell, i16 iter); //Cell-specific conversion arithmetic called by... void volts_pack (i16 iter); //Conversion of ADC value to Volts void log_highlow (); //Determines highest and lowest values void display_graph (); //Displays graph on LCD //FUNCTIONS section =========================================================== void lcd_coord () //Function to establish co-ordinates //'h_addr' selects horizonal address 'Y' (0-127) //'v_addr' selects vertical / page address 'X' (0-7) //Chip is selected automatically { u8 addr; if(h_addr<64) //Address is on Left chip (1st 64 addresses 0-63) { cs1=0; cs2=1; //Configure left chip addr = 0b01000000 + h_addr; //Horizontal address command + 0-63 lcd_write(addr,0); //Send instruction to LCD addr = 0b10111000 + v_addr; //Vertical address command + 0-7 lcd_write(addr,0); } else //Address is on right chip { en = 0; //Enable: Start low nop(); //Pause to take effect cs1=1; cs2=0; //Configure right chip addr = 0b01000000 + (h_addr-64); //Horizontal address (convert to 0-63) lcd_write(addr,0); addr = 0b10111000 + v_addr; //Vertical address lcd_write(addr,0); } } //------------------------------------------------------------------------------ void lcd_font (u8 library, u8 offset) //Function to select and display a font //Selects left and right chip when h_addr is 0 and 64 //'library' selects which font array/collection to use //'position' is sequence in which characters appear (eg: 'c' is 3rd) //'offset' becomes the variable identifier (starting at '0') { u8 i; u8 width; u8 display; if(library==5) width=6; else width=1; //Library 4 offset *= width; //There are 6 variables for each regular character, 1 for graphs // eg: 1st variable for 1st character is at offset 0 // 1st variable for 2nd character is at offset 6 for(i=0; i<width; i++) //6 writes needed per regular character, 1 for graphs & images { if(h_addr==0) //Enable left chip when starting to fill row { lcd_coord(); //Sets new address } else if(h_addr==64) //Change to right chip for addresses 64-127 { lcd_coord(); //Sets new address } if(library==4) display = graph [offset+i]; else if(library==5) display = graph1 [offset+i]; lcd_write( display, 1); //Send chosen character to LCD h_addr++; //Increment horizontal / chip select counter } } //------------------------------------------------------------------------------ void lcd_write (u8 send, u8 mode) //Function to send an instruction or data to the LCD //'send' is the byte to be sent to LCD //'mode' is 0=Instruction and 1=Data //Addressing (including chip selection) is done elsewhere // (needs to be called before this function) { data = 0; //Initialise port trisc = 1; //PortC not outputting data (made an Input) en = 0; //Enable: Start low nop(); //Pause to take effect rw = 0; //RW: 0=Write if(mode==0) rs=0; //RS: 0=Instruction else rs=1; //RS: 1=Data nop(); //140ns delay before making Enable high (nop = 500ns @ 8Mhz) en = 1; //Enable: High to execute nop(); //450ns delay before making Enable low trisc = 0; //Port C: 0=Output to make data available data = send; //Set the data (instruction or screen character) to be sent nop(); en = 0; //Enable: Low to end the write activity nop(); rw = 1; //Disable writing data = 0; //Initialise port (in case port is read to check status) trisc = 1; //PortC no longer an output } //----------------------------------------------------------------------------- void lcd_refresh () //Function to clear screen and 'fix' stuff after interrupts { u8 b; u8 i; s_addr = 0b11000000; //Set scrolling to top (off) lcd_write(s_addr,0); for(b=0; b<8; b++) //Loop 8 times for all rows/'pages' ('X') { h_addr = 0; v_addr = b; for(i=0; i<128; i++) //Write accross whole screen { lcd_font(5,17); //Space } } } //----------------------------------------------------------------------------- void measure_cells (i16 iter) //Function to measure cell voltages //'iter' is number of times to perform measurements // (more improves accuracy) //iter must be 1, 2, 4, 8, 16, 32, 64, 128 or 256 //adc_result array gets cummulative measurements { i16 i; //Measure cells for(i=0; i<pack_size; i++) //Initialise array for cells needed { adc_result[i] = 0; //Initialise variable } for(i=0; i<iter; i++) //Measure 'iter' times to smooth results { adc(pack_size); //10 measurements per iteration less highest and lowest = sum of 8 } } //----------------------------------------------------------------------------- void adc (u8 cells) //Function to trigger AD conversions //'cells' are number of cells being measured //Note: '2Tad' automatic acquisition delay has been configured //Function keeps adding conversion results to adc_result array { u8 i; u8 k; u8 channel = 0; i16 highest[7] = 0; i16 lowest[7] = 0; for(k=0; k<10; k++) //Measure each cell 10 times (improves accuracy) { for(i=0; i<cells; i++) //Run ADC for number of cells being measured (AN0 to AN9) { //Select channel channel = i; //Select cell number for next measurement //eg: For 5th cell (AN4) i=4, 6th cell (AN8) i=5 if(i==5) channel+=3; //AN5-AN7 don't exist on this chip so jump to AN8 after AN4 adcon0 = (channel*4) +1; //Configures each channel (channel*4) and enables AD module (+1) //eg: 5th cell: i=4, channel=4, 4*4+1=17 ie: 0b010001=AN4 //eg: 6th cell: i=5, channel=5+3=8, 8*4+1=33 ie: 0b100001=AN8 //Run ADC pir1.6 = 0; //ADIF: Clear the ADC Complete flag adcon0.1 = 1; //GO: Start ADC acquisition while(adcon0.1==1); //Wait for conversion to complete (becomes 0) //Merge results MAKESHORT (result, adresl, adresh); //Merges high and low registers adc_result[i] += result; //Sum each cell's results //Determine highest measurement if (k==0) highest[i] = result; else { if(result>highest[i]) highest[i]=result; } //Determine lowest measurement if (k==0) lowest[i] = result; else { if(result<lowest[i]) lowest[i]=result; } } } //Deduct highest and lowest measurements to exclude annomalies for(i=0; i<cells; i++) //Run ADC for number of cells being measured (AN0 to AN9) { adc_result[i] -= highest[i]; //Reduces 10 measurements to 9 adc_result[i] -= lowest[i]; //9 becomes 8 } } //----------------------------------------------------------------------------- void volts_pack (i16 iter) //Function to convert ADC values to cell voltages //'iter' is number of times each has been measured //Needs to be same as measure_cells() { u8 i; for(i=0; i<pack_size; i++) { convert = adc_result[i]; //Select cell value to be converted volts_calc ( (i+1), iter); //Convert ADC value to volts //'i+1' is cell number (1 is cell 1) //'convert' is cell ADC value //'iter' is # iterations the value comprises // (how many times the cell was measured) adc_result[i] = convert; //Save converted value } //Determine single cell values (cell voltages are 'cumulative' (eg: cell 2 is 1+2)) if(adc_result[6]>adc_result[5]) adc_result[6] -= adc_result[5]; //Cell 7 if(adc_result[5]>adc_result[4]) adc_result[5] -= adc_result[4]; //Cell 6 if(adc_result[4]>adc_result[3]) adc_result[4] -= adc_result[3]; //Cell 5 if(adc_result[3]>adc_result[2]) adc_result[3] -= adc_result[2]; //Cell 4 if(adc_result[2]>adc_result[1]) adc_result[2] -= adc_result[1]; //Cell 3 if(adc_result[1]>adc_result[0]) adc_result[1] -= adc_result[0]; //Cell 2 } //----------------------------------------------------------------------------- void volts_calc (u8 cell, i16 iter)//Function to convert ADC values to volts //'cell' is cell number being converted (1-7) //'iter' indicates how many times cells were measured //Requires 'convert' to be populated elsewhere { convert *= (256/iter); //Scale up to 2048 times bigger than single measurement //adc(pack) above measures 10 times, discards 2 = 8 //Increase by a factor of 256 to get to 2048 (2048/8=256) //2048 is chosen via spreadsheet to increase accuracy //If iter=1 values will be x256 //If iter=16 values will be x16 //If iter=256 values will be x1 if(cell==1) //Adjust 1st cell (most have different resistor dividor ratio) { convert += 6250; //Compensate for PIC rounding (always down) convert /= 6250; //Scale down - per spreadsheet } else if(cell==2) //2nd cell (different resistor ratio) { convert += 6270; convert /= 6270; } else if(cell==3) //3th cell { convert += 6270; convert /= 6270; } else if(cell==4) //4th cell { convert += 4623; convert /= 4623; } else if(cell==5) //5th cell { convert += 3818; convert /= 3818; } else if(cell==6) //6th cell { convert += 3123; convert /= 3123; } else //7th cell { convert += 2770; convert /= 2770; } } //############################################################################## //Program eratic when this is here; works in lcd_deisplay() void log_highlow () //Function to determine highest and lowest logged voltages (mode 2) { u8 i; //Determine highest values for(i=0; i<96; i++) //Finds highest out of 96 measurements for each cell { if(i==0) { log_high[0]=log1[i]; //Start with first value log_high[1]=log2[i]; log_high[2]=log3[i]; log_high[3]=log4[i]; log_high[4]=log5[i]; } else { if(log1[i]>log_high[0]) log_high[0]=log1[i]; if(log2[i]>log_high[1]) log_high[1]=log2[i]; if(log3[i]>log_high[2]) log_high[2]=log3[i]; if(log4[i]>log_high[3]) log_high[3]=log4[i]; if(log5[i]>log_high[4]) log_high[4]=log5[i]; } } for(i=0; i<pack_size; i++) //Finds highest of all cells measured { if(i==0) log_highest=log_high[i]; else { if(log_high[i]>log_highest) log_highest=log_high[i]; } } //Determine lowest values for(i=0; i<96; i++) { if(i==0) { log_low[0]=log1[i]; //Start with first value log_low[1]=log2[i]; log_low[2]=log3[i]; log_low[3]=log4[i]; log_low[4]=log5[i]; } else { if(log1[i]<log_low[0]) log_low[i]=log1[0]; if(log2[i]<log_low[1]) log_low[i]=log2[1]; if(log3[i]<log_low[2]) log_low[i]=log3[2]; if(log4[i]<log_low[3]) log_low[i]=log4[3]; if(log5[i]<log_low[4]) log_low[i]=log5[4]; } } for(i=0; i<pack_size; i++) //Finds lowest of all cells measured { if(i==0) log_lowest=log_low[i]; else { if(log_low[i]<log_lowest) log_lowest=log_low[i]; } } } //############################################################################## void display_graph () //Function to display logged data in graph (mode2) //'cells' indicates all (0) or individual cells (1-5) { u8 d; u8 i; u8 k; i16 base; //Value for lowest pixel in row (eg: 440 to 447 in top row) i16 disp; //Converts integers to decimals for displaying data u8 line; //Determines markers on vertical axis u8 buff[4]; bit ten; bit hun; u8 offset; //############################################################################## //Special test section - When this code is here it works /* //Normally with global variables i16 log1[97]; //Stores measurements for cell 1 etc... i16 log2[97]; i16 log3[97]; i16 log4[97]; i16 log5[97]; //Normally in main() for(i=0; i<96; i++) { log1[i] = (i16)adc_result[0]; //Store Cell 1's ADC values log2[i] = (i16)adc_result[1]; //Cell 2 etc... log3[i] = (i16)adc_result[2]; log4[i] = (i16)adc_result[3]; log5[i] = (i16)adc_result[4]; } //Normally a separate function void log_highlow() //Determine highest values for(i=0; i<96; i++) //Finds highest out of 96 measurements for each cell { if(i==0) { log_high[0]=log1[i]; //Start with first value log_high[1]=log2[i]; log_high[2]=log3[i]; log_high[3]=log4[i]; log_high[4]=log5[i]; } else { if(log1[i]>log_high[0]) log_high[0]=log1[i]; if(log2[i]>log_high[1]) log_high[1]=log2[i]; if(log3[i]>log_high[2]) log_high[2]=log3[i]; if(log4[i]>log_high[3]) log_high[3]=log4[i]; if(log5[i]>log_high[4]) log_high[4]=log5[i]; } } for(i=0; i<pack_log; i++) //Finds highest of all cells measured { if(i==0) log_highest=log_high[i]; else { if(log_high[i]>log_highest) log_highest=log_high[i]; } } //Determine lowest values for(i=0; i<96; i++) { if(i==0) { log_low[0]=log1[i]; //Start with first value log_low[1]=log2[i]; log_low[2]=log3[i]; log_low[3]=log4[i]; log_low[4]=log5[i]; } else { if(log1[i]<log_low[0]) log_low[i]=log1[0]; if(log2[i]<log_low[1]) log_low[i]=log2[1]; if(log3[i]<log_low[2]) log_low[i]=log3[2]; if(log4[i]<log_low[3]) log_low[i]=log4[3]; if(log5[i]<log_low[4]) log_low[i]=log5[4]; } } for(i=0; i<pack_log; i++) //Finds lowest of all cells measured { if(i==0) log_lowest=log_low[i]; else { if(log_low[i]<log_lowest) log_lowest=log_low[i]; } } */ //End of special test section //############################################################################## if(log_highest>56) base=log_highest-7; //Highest point at top of screen else base=49; //Bottom of 7th row starts at 0.01v for(k=0; k<7; k++) //Rows ('pages') in graph (each 8 dots high) { h_addr = 0; //Initialise horizontal counter (toggles chip select) v_addr = k; //Sets vertical counter base -= k*8; //Adjusts values relative to top of graph (eg: 440 if k=0, 432 if k=1) //High/low info in left margin if(cell_num>0) //Displays individual cells, 1 at a time { if(k==0) //High value for cell at top { disp=log_high[(cell_num-1)]; //eg: Cell 3 is array variable 2 uitoa_dec (buff, disp, 3); buff[0] -= 0x30; //Convert ASCII to single character (-0x30) lcd_font(5,buff[0]); //Display value only if 100 or more lcd_font(5,12); //'.' buff[1] -= 0x30; lcd_font(5,buff[1]); //Tenths buff[2] -= 0x30; lcd_font(5,buff[2]); //Hundredths } else if(k==1) //Lowest value measured on 2nd row { disp= log_low[(cell_num-1)]; uitoa_dec (buff, disp, 3); buff[0] -= 0x30; //Convert ASCII to single character (-0x30) lcd_font(5,buff[0]); //Display value only if 100 or more lcd_font(5,12); //'.' buff[1] -= 0x30; lcd_font(5,buff[1]); //Tenths buff[2] -= 0x30; lcd_font(5,buff[2]); //Hundredths } else if(k==2) //Cell number on 3rd row { lcd_font(5,17); //Normal spaces (x 6px) lcd_font(5,11); //'#' lcd_font(5,(cell_num)); //Cell number lcd_font(5,17); //Normal spaces (x 6px) } else //Spaces on other rows { for(i=0; i<4; i++) lcd_font(5,17); //Normal spaces (x 6px) } } if(cell_num==0) //Displays all cells { if(k==0) //Highest of all cells at top { disp=log_highest; //Highest in pack uitoa_dec (buff, disp, 3); buff[0] -= 0x30; //Convert ASCII to single character (-0x30) lcd_font(5,buff[0]); //Display value only if 100 or more lcd_font(5,12); //'.' buff[1] -= 0x30; lcd_font(5,buff[1]); //Tenths buff[2] -= 0x30; lcd_font(5,buff[2]); //Hundredths } else if(k==1) //Lowest of all cells on 2nd row { disp=log_lowest; //Lowest in pack uitoa_dec (buff, disp, 3); buff[0] -= 0x30; //Convert ASCII to single character (-0x30) lcd_font(5,buff[0]); //Display value only if 100 or more lcd_font(5,12); //'.' buff[1] -= 0x30; lcd_font(5,buff[1]); //Tenths buff[2] -= 0x30; lcd_font(5,buff[2]); //Hundredths } else if(k==2) //Cell number on 3rd row { lcd_font(5,13); //A lcd_font(5,14); //l lcd_font(5,14); //l lcd_font(5,pack_log); //Number of cells measured } else //Spaces on other rows { for(i=0; i<4; i++) lcd_font(5,17); //Normal spaces (x 6px) } } //Vertical axis (scale markings every 1.00 and 0.10v) lcd_font(4,8); //1px spaces (padding) ten = 0; //Initialise 10 step counter (every 0.10v) hun = 0; //100 step counter (every 1.00v) for(i=0; i<8; i++) //Test all 8 vertical bits to see if multiple of 10 or 100 { if( (base+i)/10 > (base-1+i)/10 ) //Test for multiples of 0.10v ('10' = 0.10v) //PICs always rown down //So, this test will only increment when multiples of 10 are reached //base is the lowest value in the current row (eg: 440) //base-1 is the value immediately neneath it (eg: 439) //The test will be true once only when changing to a higher multiple of 10 { ten = 1; //0.10v flag offset = i; //Vertical location } if( (base+i)/100 > (base-1+i)/100 ) //Test for multiples of 1v ('100' = 1.00v) { hun = 1; //1v flag ten = 0; //0.10v flag offset = i; //Vertical location } } if(hun==1) { for(d=0; d<5; d++) lcd_font(4,offset); //Create 5 dots to indicate a multiple of 100 } else if(ten==1) { for(d=0; d<3; d++) lcd_font(4,8); //Create 3 blank spaces for smaller indicator for(d=0; d<2; d++) lcd_font(4,offset); //Create 2 dots to indicate a multiple of 10 } else { for(d=0; d<5; d++) lcd_font(4,8);//Create 5 blank spaces if no multiples of 10 or 100 } lcd_font(4,9); //|Vertical line lcd_font(4,8); //1px space (padding) //Graph lines for(i=0; i<96; i++) //Scroll across screen pixel by pixel (96 logged measurements) { if(cell_num==1) //Cell 1 { if( log1[i]>(base-1) && log1[i]<(base+8) )//eg: between 440 and 447 (in top row's range) { line = (u8)(log1[i]-base); //Converts to 7-0 (eg: 440 becomes 0, 447 becomes 7) lcd_font(4,line); //Send this offset location to LCD } else lcd_font(4,8); } if(cell_num==2) //Cell 2 { if( log2[i]>(base-1) && log2[i]<(base+8) ) { line = (u8)(log2[i]-base); lcd_font(4,line); } else lcd_font(4,8); } if(cell_num==3) //Cell 3 { if( log3[i]>(base-1) && log3[i]<(base+8) ) { line = (u8)(log3[i]-base); lcd_font(4,line); } else lcd_font(4,8); } if(cell_num==4) //Cell 4 { if( log4[i]>(base-1) && log4[i]<(base+8) ) { line = (u8)(log4[i]-base); lcd_font(4,line); } else lcd_font(4,8); } if(cell_num==5) //Cell 5 { if( log5[i]>(base-1) && log5[i]<(base+8) ) { line = (u8)(log5[i]-base); lcd_font(4,line); } else lcd_font(4,8); } } //end graph lines } //end 'k' counter (7 rows) } //end function //=========================================================================== void main() //main program { bit b; u8 d; i16 i; bit capture; //Initialise all ports, etc porta=0; portb=0; portc=0; //Start low lata=0; latb=0; latc=0; //Start low //Set oscillator frequency osccon.6 = 1; osccon.5 = 1; osccon.4 = 1; //8mhz //osccon.4 = 0; //4mhz //Main port settings (1=Input 0=Output) //Pin1 RE3 ICSP (tris.3 does not exist) trisa.0 = 1; //2 RA0 AN0 Cell1 trisa.1 = 1; //3 RA1 AN1 Cell2 trisa.2 = 1; //4 RA2 AN2 Cell3 trisa.3 = 1; //5 RA3 AN3 Cell4 trisa.4 = 0; //6 RA4 #spare# trisa.5 = 1; //7 RA5 AN4 Cell5 trisa.7 = 0; //9 RA7 RW trisa.6 = 0; //10 RA6 DI/RS trisc = 0; //11-18 RC0-7 D0-7 (LCD data) trisb.0 = 1; //21 RB0 AN12 menu push-button trisb.1 = 1; //22 RB1 AN10 select push-button trisb.2 = 1; //23 RB2 AN8 Cell6 trisb.3 = 1; //24 RB3 AN9 Cell7 trisb.4 = 0; //25 RB4 AN11 Reset trisb.5 = 0; //26 RB5 Enable trisb.6 = 0; //27 RB6 ICSP / CS1 trisb.7 = 0; //28 RB7 ICSP / CS2 //ADC settings adcon1.5 = 0; //VCFG1: Vref low = Vss adcon1.4 = 0; //VCFG0: Vref high = Vdd adcon1.3 = 0; //PCFG: AN0-9 analogue, AN10-12 digital adcon1.2 = 1; //PCFG: part of above adcon1.1 = 0; //PCFG: part of above adcon1.0 = 1; //PCFG: part of above adcon2.7 = 1; //ADFM Right justify results adcon2.5 = 0; //ACQT: Acquisition time (2 Tad - see spreadsheet) adcon2.4 = 0; //ACQT: part of above adcon2.3 = 1; //ACQT: part of above adcon2.2 = 0; //ADCS: AD conversion clock (Fosc/8 - see spreadsheet) adcon2.1 = 0; //ADCS: part of above adcon2.0 = 1; //ADCS: part of above //Interrupts rcon.7 = 0; //IPEN: Interrupt priorities disabled intcon.7 = 1; //GIE: Enables interrupts globally intcon.4 = 1; //INT0IE: RB0 interrupt enabled ('menu') intcon3.3 = 1; //INT1IE: RB1 interrupt enabled ('select') intcon2.6 = 0; //INTEDG0: RB0 interrupt on falling edge (weak pullups hold high) intcon2.5 = 0; //INTEDG1: RB1 interrupt on falling edge //Weak pullups intcon2.7 = 0; //RBPU: Weak pullups enabled for PortB (all digital input pins) //Pause delay_ms(250); //Delay to prevent programmer from interferring and allows LCD to start //Static EEPROM data logging settings eecon1.6 = 0; //CFGS: Access data not config eecon1.3 = 0; //WRERR: clear on startup in case previously set //------------------------------------------------------------------------------ //Initialise LCD etc b=1; for(i=0; i<2; i++) //Switch both halves of screen { cs1=b; b++; //Toggles chip selection bits (0=selected; 1=deselected) cs2=b; lcd_write(0b00111111,0); //Switch display on s_addr = 0b11000000; //Set scrolling to top (off) lcd_write(s_addr,0); } lcd_refresh(); //Clear screen and set scrolling to top mode = 2; //Start mode mode_min = 0; //Default smallest menu choice (wraps backwards to largest) mode_max = 2; //Default largest menu choice (wraps forwards to smallest) sel = 3; //Default selection (usually pack size) sel_min = 1; //Default minimum allowed in each mode sel_max = 7; //Default maximum allowed in each mode pack_size = 3; //Default pack size for mode 1 pack_log = 3; //Default maximum pack size for mode 2 cell_num = 3; //Default cell number capture = 0; //Mode 2 capture not performed yet for(d=0; d<7; d++) //Initialise Mode 2 array { log_high[d] = 0; log_low[d] = 0; } log_highest = 448; //Set default graph scaling log_lowest = 0; //=========================================================================== while(1) { for(i=0; i<96; i++) //96 iterations of cell measurements { measure_cells(8); //Measure cells 8 times each volts_pack(8); //Determine voltages //############################################################################## //This section copied to lcd_display() to make it work log1[i] = (i16)adc_result[0]; //Store Cell 1's ADC values log2[i] = (i16)adc_result[1]; //Cell 2 etc... log3[i] = (i16)adc_result[2]; log4[i] = (i16)adc_result[3]; log5[i] = (i16)adc_result[4]; } log_highlow(); //Determine highest and lowest logged voltages using pack_size //############################################################################## display_graph(); //Display on LCD while(1); } //end while } //end main
  23. 1. The easiest is to store data in normal RAM using variables or an array. 2. However, I suspect you are referring to program memory (ROM) which can be written to when programming with the BoostC 'rom' command and read at any time. 3. If you want your PIC program to update this data on the fly you need to have a device which supports 'self-write' ('Enhanced Flash' versions in the 16F series or available in most or all? 18F's). Harder than 1 or 2. 4. External memory will be more work than 3. David.
  24. DavidT

    Delays On 18f

    Hi, The following code is intended to populate EEPROM to confirm that the PIC is working. When I use delay_ms(1) at 8MHz it populates the first three bytes of EEPROM as intended. When I use delay_s(1) at 8MHz EEPROM does not get populated. When I change the clock to 4MHz delay_s(1) EEPROM gets populated. So there appears to be a problem with delay_s(1) at 8MHz. I'm using an 18F2523 with IDE 6.81 on XP. Thanks, David. #include <system.h> //Core configuration (rest left at default): #pragma DATA 0x300001, 0b1000 //Config1H: Internal oscillator with IO on RA6 and 7 #pragma DATA 0x300006, 0b10000001 //Config4L: Debug, Extended instructions and low voltage programming all off #pragma CLOCK_FREQ 8000000 //8MHz void eeprom_write() //Function to write to EEPROM flash memory { eecon1.2 = 1; //WREN: enable writing to memory intcon.7 = 0; //Disable all interrupts while writing to memory pir2.4 = 0; //EEIF: Clear this bit which gets set after each write eecon2 = 0x55; //Required before writing to memory eecon2 = 0xAA; //Required before writing to memory eecon1.1 = 1; //WR: Writes data eedata to address eeadr while(eecon1.1==1); //Wait for write to complete (becomes 0 when complete) eecon1.2 = 0; //WREN: Disable writing to memory (while not in use) } void main() { char i; delay_s(1); eecon1.7 = 0; //EEPGD: Access data memory eecon1.6 = 0; //CFGS: Access data not config eecon1.3 = 0; //WRERR: clear on startup in case previously set for(i=0; i<3; i++) //Test to ensure PIC is working { eeadr = i; eedata = i+1; eeprom_write(); } while(1); }
  25. I can't guarantee that the following code will work but I've tried to extract the relevant parts from a project of mine: David. #include <system.h> #pragma DATA _CONFIG, _FCMEN_OFF & _IESO_OFF & _BOR_ON & _CPD_OFF & _CP_OFF & _MCLRE_OFF & _PWRTE_ON & _WDT_OFF & _INTOSCIO #pragma CLOCK_FREQ 4000000 #define rs portb.4 //Register Select #define en portb.5 //Enable #define data portc //Characters or instructions for sending to LCD //Assume RW is permamnently low void main(void) { //Initialise all ports porta=0; portb=0; portc=0; //Main port settings (1=Input 0=Output) trisa = 0; //All pins Output trisb = 0; //All pins Output except... trisb.4 = 1; //RB4 trisb.5 = 1; //RB4 trisc = 0; //All pins Output //Initialise LCD char i; //Decalre variable for counter delay_ms(250); //Wait for LCD to start //'Set Function' for(i=0; i<3; i++) //Send instruction 3 times to stabilise display { data=0b.00111000; //8bit, 2 lines, 5x7 rs=0; //Set RS low for instructions nop(); //Brief delay en=1; //Set Enable high before writing nop(); //Brief delay en=0; //Execute by pulling low delay_ms(1); //Wait to complete } //'Display Clear' and return cursor to home position data=0b00000001; //Clear display rs=0; nop(); en=1; nop(); en=0; delay_ms(1); //'Set Entry Mode' sets cursor auto-increment direction data=0b00000110; //Increment cursor (right) after writing; don't shift display rs=0; nop(); en=1; nop(); en=0; delay_ms(1); //'Cursor/Display Shift' sets cursor move direction data=0b00010100; //Increment address and moves cursor right rs=0; nop(); en=1; nop(); en=0; delay_ms(1); //'Display ON' enables display/cursor data=0b00001111; //Display on, cursor on, blinking on rs=0; nop(); en=1; nop(); en=0; delay_ms(1); //Send data data=0x31; //Send ASCII '1' rs=1; nop(); en=1; nop(); en=0; delay_ms(1); data=0x32; //Send ASCII '2' rs=1; nop(); en=1; nop(); en=0; delay_ms(1); while(1); } //end main
×
×
  • Create New...