Jump to content

drumanart

EstablishedMember
  • Content Count

    48
  • Joined

  • Last visited

Everything posted by drumanart

  1. Hello I use since ages Sourceboost with Linux and MPLAB IDE 8,90 under wine (OS UBUNTU). Recently I migrated to MPLABX (Linux version) using the free version of MPLABXC8 compiler. As I have good experiences with SourceBoost I'd would like to go ahead with this complier and purchase the newest version 7.43 and use it with MPLABX IDE under Linux. Did any body make it work? Kind regards Martin
  2. Hello. I use since a couple of years a licensed version of BoostC C Compiler (Version 6.95). Now, as a plan to upgrade to a newer, actual, version and also to migrate to MPLAB-X (I use still MAPLAB 8.5 with LINUX and wine what works like a charm) I have a doubt: If I buy the C++ Compiler can I compile (re-use) code written for the BoostC C compiler version? In any case as I plan to go on with LINUX I suppose that I will have some issues to make SourceBoost work. Thanks Martin
  3. Hello. Code for 18F4420 At the beginning of my code I tell the preprocessor to activate the watch dog. #pragma DATA _CONFIG2H, _WDT_ON_2H & _WDTPS_2048_2H // WDTON, prescaler 1/2024. Is there a possibility to deactivate the watchdog while the code is running but not with _asm clrwdt? Thanks Martin
  4. Thanks for the LUT solution. As the compass works with 16bit resolution and I have to calculate, beside the heading, also pitch and roll (with an incorporated accelerometer) I thinks the easiest way is to send all raw data (6 bytes for the magnetometer and 6 bytes for the accelerometer) to the computer and solve the "big" calculation with the PC. I can do this quite straight forward with SuperCollider. The other thing is, as I mentioned above, that my browser shows rare signs if I lock at other threads: so, for example: ( for ( // ( for ) // &#41 for "; Any succestion Thanks Martin
  5. Hello, I made a small PCB for the LSM303 electronic compass. The unit communicates with a I2C protocol and I made my one software functions to communicate with the unit what works great. Now, to get something useful out of the row data I have to use some math. Following the app notes of the LSM303 I have to calculate: Heading = arctan (Yh/Xh) Is there a mathematic library in SourceBoost. I work with a licend 6,95 Version. The other thing is that my browser (Chromium with Linux) want show the special signes from other threads correctly. My browser shows: ( for ( // ( for ) // &#41 for "; and so on .. It is difficult to read the code. Thanks Martin (
  6. Ok, I respond to myself: As nobody in the forum seems to run MPLABX IDE under Linux (UBUNTU) and before inverting for a new programmer ICD3 (ICD2 want work with MPLABX IDE ) and before purchasing a new version of SourceBoost (with drivers for MPLABX IDE) I installed PIKLAB IDE. IT WORKS GREAT and my ICD2 clone runs even faster then ever in MPLAB IDE under WIndows. Martin
  7. Hello. I use UBUNTU (LINUX) as an OS and run, using wine, MPLAB IDE 8.5 with a licensed SourceBoost v.6.95 This works fine but is a little slow. No, since Microchip lanced the MPLAB X IDE there is also a version for LINUX and I red that SourceBoost v.7.05 has the drivers to run the program with the new environment. Does this works also on a LINUX (UBUNTU) without fiddling with wine, and did someone install it successfully? ( I can't find any topics). Thanks Martin
  8. Jorge, I found the bug, I had the T1CON, 3 (T1OSCEN) flag enabled. This is why the program always jumped to the void interrupt(void ) function. Both, the TMR0 and TMR1 timers, as well as the SSPIF flag are set as high priority and I handle them using the void interrupt(void ) function and the program works great. If I put an oscilloscope at the PW output, even in receiving continuous data stream from the wireless SPI unit (nRF24L01 is great), the puls-with is not affected at all. I did a little trial to manage the SPI in pooling the BF flag and also this works. As I have now the abilities to handel18 stepper motors the last thing I need to do is to set up the CCP module for two other PW to use with two independent servo motors. I suppose I will be in troubles shortly because the SPI module also uses the TMR2 oscillator. Thanks for you help. Martin
  9. Oh yes, the SSPIP is flag is the PIR1,3 and the TMR1F the PIR1,0. Yesterday I tried to find the failure of my interrupt mess without having success. Still, as soon as I start the timers (TMR0, TMR1) fto run the PW the communication with the SPI unit fails. Today I will handle the SPI pooling the SSPIF in the main function. Would it be also possible to use the SSPSTAT, BF (buffer full) flag to handle the SPI module? Thanks for your passion. Martin
  10. Yeep Jorge. Thanks for the advise of the AND and OR gates graphics at page 92 of the 18Fxx data-sheet this is helpful for understanding of interrupts. As I had the PW for two servos with TMR0, TMR1 working really nicely and on the other hand the SPI unit (the Nordic 24L01 wireless radio) ) using another program was working fantastic (in my opinion) I didn't expect to have this troubles. I'm sure the mess is already at the SPI interrupt PIR1,SSPIF. Probably I forgot to clear somewhere the SSPIF as I did with the TMR1IF flag (this is why I forced the GIE flag to 1) . I suppose this messes up the further interrupt routines. I'll get there, for sure ..... kind regards Martin
  11. Hi Jorge. So, I assume only if the IPEN of the RCON register is set the High/Low priority bits are valid and an interrupt_low function is activated. Now, could I handle the PW routine with the TMR0 and TMR1 flags as low priority interrupts in the interrupt_low function and handle the INT2IF and the SSPIF for the ISP unit as high priority interrupts? ( I don't find a way to set TMR1 as low priority, nor the SSPIF) Or is it easier to set the RCON bit as 0 and work in PIC16CXXX Compatibility mode. What is the standard way if one creates PW with timers and have a ISP unit connected. Thanks Martin I
  12. The thing is slightly more complex, as the program creates two PW, with timer0 and timer1. At start up I have to set the GIE & PEIE to configure the ISP module (wirless radio nRF24L01). I changed the messy code following your advice and I can receive wireless data from the nRF24L01, but as soon as I start the timers (the disabled code underneath) the INT2IF want get high anymore and I can't receive wireless data any more. So, either the PW works or the nRF24L01 works. Still there is a missmatch. Thanks Martin void interrupt(void){ if (spi_interrupt){ spi_handle_interrupt(); } else if (int2if){ int2if = 0; // IRQ of nRF24L01, if low reads data buffer. RX_TX_nRF(); } //reload 20ms periode time. else if (tmr0if){ tmr0l = 100; // Value for TIMER0: 100d.= 20ms - 50Hz tmr0if = false; // Clear INTCON overflow bit.(TMR0) count = 1; PW_0 = true; // Strats SERVO 1 pulse. tmr1on = true ; // Enable TIMER1. tmr1if = false; // PIR1 (clear timer1 overflow flag) tmr1h = TIME1_FIX; // Load fixed value into TIMER1 register; tmr1l = TIME_ON1; // Variable value for Servor 1. } else if ((tmr1if) && (count == 1)){ PW_0 = false; // Stops SERVO 1 pulse. PW_1 = true; // Starts SERVO 2 pulse. tmr1if = false; // PIR1 (clear timer1 overflow flag). tmr1h = TIME1_FIX; // Fixed value; tmr1l = TIME_ON2; // Value to be loaded for Servor 2. count++; } else if ((tmr1if) && (count == 2)){ PW_1 = false; // Stops SERVO 2 pulse. tmr1on = false; // disable TIMER1. count = 0; } gie = true; // re-enable GIE. } void main() { init(); // device and peripheral initialisation. unsigned char get_byte; char count = 0x02; nrf_rx_mode(); // nRF receiver mode & power up. peie = false; gie = false; // disable all interrupts. intcon2 = INTCON2_CONF; // 00000000b Pullup enabled, Interrupt RB2 falling edge, Low priority. intcon3 = INTCON3_CONF; // 00010000b RB2, INT2IE, enabled, INT2IP disabled. peie = true; // peripheral interrupts inabled. int2if = false; // clear a possible pending interrupt. // sets the timers for the PW modulation. // if I enable this code the wireless module wont work, but the PW works. /*t0con = TIME0_CONF; // Timer0 enabled, precaler set to 1/128, 8 bit and load tmr0l = TIMEFR_VAL; // Value for TIMER0: 100d.= 20ms - 50Hz. t1con = TIME1_CONF; // 00111000b, T1CON, 1/8 presc. Timer1 disabled. tmr1h = TIME1_FIX; // 11111110b // to get the above times in ms. (8 bit) tmr1if = false; // PIR1 (clear timer1 overflow flag). pie1 = PIE1_CONF; // TMR1 overflow bit enabled & EUSART interrupt enabled. tmr0ie = true; // timer 0 ext. interrupt enabled.*/ gie = true; // start all interrupts. while (1){ PW_LED_OnOff(); // toggle LED Off. } } // // // function sends the received data to USART void RX_TX_nRF(){ unsigned char get_byte; char count = 0x02; PW_LED_OnOff(); // DEBUG ONLY. nrf_read_fifo(); // reads data from the payload. while (count < 5){ // control function, prints to serial port. get_byte = nrf_get_byte(count); // gets the data from data[] array. serial_printf(get_byte); // print the return value to the terminal. count++; } count = 0x02; // set the pointer in spi_exchange function. nrf_reset_status(); // clear nrf24L01 status reg. } // // void init(){ osccon = 01110000b; // internal oscillator at 8 MHz. while (!iofs); // iofs OSCCON stable bit. adcon1 |= 0x0F; // All digital IO's, no analog ports required. trisa = 10111111b; // RA6, ID_LED. trisb = 00000100b; // RB0, RB1 PW out. RB2 IRQ for nRF24L01. trisc = 11000000b; // RC6, RC7 RX; RC0 LED white, RC4 LED yellow. portb = 0x00; gie = true; // set GIE & PEIE to configure the nRF24L01. peie = true; // Serial interface serial_init(34); // (51) 38400 baud; (34) 57600 baud; DEBUG, before: BRG = 25 (19200 baud at 8MHz). serial_printf("initializing serial port"); serial_print_lf(); // Wireless interface nrf_init(); // init the nRF24L01. serial_printf("nRF24L01 config done..."); serial_print_lf(); return; }
  13. Hello. I spent a entire afternoon in trying to get en interrupt on a PIC18F4420 on portb,2 working. At portb,2 I have the IRQ pin of an nRF24L01 attached. So, this pin drives low when data is received and I would like that the program jumps to the void interrupt(void) routine. For test purpose the program stays for ever in the interrupt function. With my code the int2if flag gets high before a change of portb,2 occurs, but the idea is that the interrupt happens if the pin is pulled down. To configure the PIC I made an init function: . void init(){ osccon = 01110000b; // internal oscillator at 8 MHz. while (!iofs); // iofs OSCCON stable bit. adcon1 |= 0x0F; // All digital IO's, no analog ports required. trisb = 00000100b; // PortB, RB2 In, used to provoke an interrupt. intcon = INTCON_CONF; // 11101000b, GIE/PEIE enabled, PortB interrupt on change enabled, TMR0IE enabled, rcon = RCON_CONF; // 00011100b, interrupt priority disabled. intcon3 = INTCON3_CONF; // 10010000b INT2IP enabled, RB2, INT2IE, enabled. intcon2 = INTCON2_CONF; // 00000001b Pullup enabled, Interrupt RB2 falling edge, High priority. } void interrupt(void){ char aux = portb; if (int2if){ // to see if something happens. while(1); } } Thanks Martin Interrupt_on Portb.c
  14. Hi Jorge. I have seen that you handle the RX data also in the ISR. Unfortunately your code want run in Sourceboost neither in MPLAB so (for me) it is not so easy to follow entirely your ideas. Somehow I understand that you resend data to the servos every 20ms, but I can't find where you handle the "Elapsed20ms" variable. Thanks Martin
  15. This is great, I just printed the code and I go into it this days. My two SERVOS work now quite nice, but still, my main problem is the data transmission. With my Easy Radio(ER400TRS) I have some problem to send packages of three bytes: "header" 0xFF; "channel" 0x00/0x01) and "data" 0x00 to 0xFF. So, the past weekend I made a new protocol sending only two bytes. 10 bits for the SERVO data and 6 bites for addressing. This works best until know. Probably I forget the EASY RADIO and do the wireless transfer with the NORDIC 24L01. This units allow sending packages until 32 bytes. Two month ago I made a small PCB with an accelerometer and a gyro sending 6 different data wireless to the computer. It works very stable and fast. Thanks a lot for your help Martin
  16. Hello Jorge. Yes, as I use a wireless module (Easy Radio ER400TRS) at a baudrate of 38400 a have to investigate first whether the data arrive correctly or if I have already bytes missing during data transfer. May I'm in the right in thinking to create an array for the incoming data (as a buffer) and adjust the SERVOS as fast as possible to the target value afterwards? PS. Last night when I was already in bed I had the flash that I don't have to handle the RCIF flag in the ISR. So I got up again and I moved it to the main function. Uff, this was a long one ..... Thanks very much for your help Martin
  17. Sorry the code was wrong pasted, here again: void main(void) { osccon = 01110000b; // OSCCON int Osc, 8 Mhz. while (!iofs); // DEBUG without iofs OSCCON stable bit. init(); // Port settings etc. //short pw_data = 120; // Servo middle position. char count_aux; while(1){ _asm clrwdt; // The watchdog. if (header == 0xFF){ header = 0x00; // set header back. switch (ch){ case 0: TIME_ON1 = pw_data; break; case 1: TIME_ON2 = pw_data; } } } } // // void interrupt(void){ char count_aux, dummy; //reload 20ms periode time. if (tmr0if){ tmr0l = 100; // Value for TIMER0: 100d.= 20ms - 50Hz tmr0if = false; // Clear INTCON overflow bit.(TMR0) count = 1; PW_0 = true; // Strats SERVO 1 pulse. tmr1on = true ; // Enable TIMER1. tmr1if = false; // PIR1 (clear timer1 overflow flag) tmr1h = TIME1_HI; // Load fixed value into TIMER1 register; tmr1l = TIME_ON1; // Variable value for Servor 1. ID_LED = false; } if ((tmr1if) && (count == 1)){ PW_0 = false; // Stops SERVO 1 pulse. PW_1 = true; // Starts SERVO 2 pulse. tmr1if = false; // PIR1 (clear timer1 overflow flag). tmr1h = TIME1_HI; // Fixed value; tmr1l = TIME_ON2; // Value to be loaded for Servor 2. count_aux = count++; return; } if ((tmr1if) && (count == 2)){ PW_1 = false; // Stops SERVO 2 pulse. tmr1on = false; // disable TIMER1. count = 0; return; } if (rcif) { header = rcreg; // 1st byte is header. while ((!rcif) || (!t0)); // t0 is a fuse to avoid endless looping. ID_LED = true; ch = rcreg; // 2nd byte is channel. while ((!rcif) || (!t0)); // t0 is a fuse to avoid endless looping. pw_data = rcreg; // 3rd byte is data. } } // //
  18. Yeep Jorge, So I did and I get a continuous puls for both SERVOS. Only when I set the INTCON GIE and PEIE bit high also the pie1.RCIE jumps to the ISR. Now, what I did is, I handle the RCIE data also in the ISR. My main code only assigns the incoming data with global variables to its corresponding SERVOS. Uff, it works and connecting a oscilloscope, the PWM locks stable and continuous and incomming data, as far as I can see it, want affect it's flow, but still, if I turn the slider my SERVO jumps. I suppose if I get it work to seperate the RCIE from the ISR the result will by finally how it has to be. If you are so kind to have a quick glance at my ISR weather my logic is right, I would appreciate it a lot. Cheers Martin void interrupt(void){ char count_aux, dummy; //reload 20ms periode time. if (tmr0if){ tmr0l = 100; // Value for TIMER0: 100d.= 20ms - 50Hz tmr0if = false; // Clear INTCON overflow bit.(TMR0) count = 1; PW_0 = true; // Strats SERVO 1 pulse. tmr1on = true ; // Enable TIMER1. tmr1if = false; // PIR1 (clear timer1 overflow flag) tmr1h = TIME1_HI; // Load fixed value into TIMER1 register; tmr1l = TIME_ON1; // Variable value for Servor 1. ID_LED = false; }[/font][/color] [color=#282828][font=helvetica, arial, sans-serif] if ((tmr1if) && (count == 1)){ PW_0 = false; // Stops SERVO 1 pulse. PW_1 = true; // Starts SERVO 2 pulse. tmr1if = false; // PIR1 (clear timer1 overflow flag). tmr1h = TIME1_HI; // Fixed value; tmr1l = TIME_ON2; // Value to be loaded for Servor 2. count_aux = count++; return; } if ((tmr1if) && (count == 2)){ PW_1 = false; // Stops SERVO 2 pulse. tmr1on = false; // disable TIMER1. count = 0; return; }[/font][/color] [color=#282828][font=helvetica, arial, sans-serif] if (rcif) { header = rcreg; // 1st byte is header. while ((!rcif) || (!t0)); // t0 is a fuse to avoid endless looping. ID_LED = true; ch = rcreg; // 2nd byte is channel. while ((!rcif) || (!t0)); // t0 is a fuse to avoid endless looping. pw_data = rcreg; // 3rd byte is data. } } void main(void) { osccon = 01110000b; // OSCCON int Osc, 8 Mhz. while (!iofs); // DEBUG without iofs OSCCON stable bit. init(); // Port settings etc. //short pw_data = 120; // Servo middle position. char count_aux; while(1){ _asm clrwdt; // The watchdog. if (header == 0xFF){ header = 0x00; // set header back. switch (ch){ case 0: TIME_ON1 = pw_data; break; case 1: TIME_ON2 = pw_data; } } } } // //
  19. Hello very patiently Jorge. Yes I understand your advise, but my problem is, to make that a TMR1 overflow jumps to the ISR I have to set the RCON ipen bit (I could not yet find an other solution). So if I set the ipen bit, data received indicated by the rcif bit jumps also to the ISR. I would have to put mostly of my code to the ISR, right? Kind regards Martin
  20. Hi Jorge. I was for two ill, but yesterday I went ahead with the program. As I can't make the TMR1 jumping into the ISR routine without setting the RCON ispen flag Hi, I did the program flow the following way. I start (enable) the TMR1 in the ISR routine and handle the rest in the main routine, and then, after the second Servo pulse is executed, I disable the TMR1. This works but with durty jumps when I fiddle with the sliders (not smooth enough). If I set the RCON ispen bit, the receiver flag rcif is also handled in the isr ROUTINE. Do I have to handle the receiving data and the PWM in the ISR routine? Thanks Martin Attached I send you the code. void interrupt(void){ //reload 20ms periode time. if (tmr0if){ tmr0l = 100; // Value for TIMER0: 100d.= 20ms - 50Hz tmr0if = false; // Clear INTCON overflow bit.(TMR0) count = 1; PW_0 = true; // Strats SERVO 1 pulse. tmr1on = true ; // Enable TIMER1. tmr1if = false; // PIR1 (clear timer1 overflow flag) tmr1h = TIME1_HI; // Load fixed value into TIMER1 register; tmr1l = TIME_ON1; // Variable value for Servor 1. } } // // void main(void) { osccon = 01110000b; // OSCCON int Osc, 8 Mhz. while (!iofs); // DEBUG without iofs OSCCON stable bit. init(); // Port settings etc. short pw_data = 120; // Servo middle position. char header = 0x00, ch; // 1st.header 0xFF, 2nd channel fro ROBOREALM. while(1){ _asm clrwdt; // The watchdog. if (rcif) { tmr0on = false; header = rcreg; // 1st reads header. } if (header == 0xFF){ pw_data = RX_DATA(); header = 0x00; // Clear register. tmr0on = true; ch = data_assigne(pw_data); } if ((tmr1if) && (count == 1)){ PW_0 = false; // Stops SERVO 1 pulse. PW_1 = true; // Starts SERVO 2 pulse. tmr1if = false; // PIR1 (clear timer1 overflow flag). tmr1h = TIME1_HI; // Fixed value; tmr1l = TIME_ON2; // Value to be loaded for Servor 2. count_aux = count++; } if ((tmr1if) && (count == 2)){ PW_1 = false; // Stops SERVO 2 pulse. tmr1on = false; // disable TIMER1. count = 0; } } } // // #ifndef _C_18F4420_SERVO_V1_H_ #define _C_18F4420_SERVO_V1_H_ #ifndef false #define false 0 #endif #ifndef true #define true !false #endif #include <system.h> #include <icd2.h> #define TIMER_ON_OFF 1 #define HELP 2 #define PW_LED latc.4 //Power (yellow) LED. volatile bit tonoff@TIMER_ON_OFF.0; volatile bit help@HELP.0; volatile bit Go_Done@ADCON0.1; // Note the 16fxx chip puts this in bit 2. volatile unsigned char ad_h@ADRESH; volatile unsigned char ad_l@ADRESL; volatile bit iofs@OSCCON.2; // OSCCON stable bit. volatile bit trmt@TXSTA.1; // transmit shift registor. volatile bit tmr1if@PIR1.0; // TIMER1 overflow bit. volatile bit tmr1on@T1CON.0; // TIMER1 enable bit volatile bit tmr1ie@PIE1.0; // TIMER1 enable overfolw bit. volatile bit rcif@PIR1.5; // transmit shift registor. volatile bit cren@RCSTA.4; // 1 enable receiver. volatile bit tmr0ie@INTCON.5; // TIMER0 enable overfolw bit. volatile bit tmr0if@INTCON.2; // TIMER0 overflow bit. volatile bit int0if@INTCON.1; // TIMER0 external overflow bit. volatile bit tmr0on@T0CON.7; // TIMER0 enable bit. volatile bit gie@INTCON.7; // General interrupt flag. volatile bit peie@INTCON.6; // General interrupt flag. volatile bit ipen@RCON.7; // Interrupt Prioity enable. volatile bit t0@RCON.3; // Watchdog overflow bit.Lo = WDT overflow. #define INTCON_CONF 10100000b // GIE enabled, TMR0IE enables. #define INTCON3_CONF 10001000b // INT1IE, enabled. #define RCON_CONF 00011100b // Interrupt priority disabled. #define PIE1_CONF 00000001b #define TIME0_CONF 11000111b // Assigned to T0CON presc. 1/256, 8 bit, enabled. #define TIMEFR_VAL 01100100b // value of 100d.= 20ms - 50Hz. #define TIME1_CONF 00111000b // T1CON, 1/8 presc. Timer1 disabled. #define TIME1_LOW 10000100b // (middle pos.) 0xFF = 1ms; 0x00 = 2ms. #define TIME1_HI 11111110b // to get the above times in ms. short RX_DATA(); // get data from rcreg. void init(); // init PORT, timers, interrupts etc. char data_assigne(short); // assignes data to corresponding Servor Motor. #endif // _C_18F4420_SERVO_V1_H_
  21. Thanks for the helpful advice and I'll have a more careful lock at the interrupt handling to not complicate live more than necessary. Kind regards Martin
  22. Uff, there we are. I had the ipen RCON,7 bit not set. The bit enables together with the gie INTCON,7 the high-priority interrupts (as you know of course). Until know a Timer1 overflow never jumped to the ISR routine, this is why I tried all this funny tricks with time-loops etc. what, made the CPU running for only one task. The (hopefully) very last question: In your LED code I learned that you configure several registers with marcos. Until know I used #define Registor 00000000b to configure the right value. Is the use of marcos better? Thanks a lot for wasting so mach time Martin
  23. Hello Jorge. I just made an project in MPLAB with your code and I can't find the functions below. Is there code missing? InitLeds(); // Set Leds control initial status InitBugFlags(BugFlags); // Init flags that signal abnormal rpogram behaviour Timer0_Config(); // Configure Timer 0 ADC_Config(); // Configure ADC ADC_On(); // Turn ADC On to start sampling Load_ADC_Delay(); // Start a delay before first ADC convertion Enable_Tmr0_Int(); // Enable Timer0 interrupts Enable_Interrupts(); // Enable global interrupts to start timing Timer0_On(); // Start Timer0 Yesterday I made an other variant of my program using TMR0 as a 50Hz time-frame and TMR1 to trigger the pulses for each SERVO. Following your advice I did the following: Start the timer0 (50hz) and than send a pulse (using timer1) for Servo 1 and right afterwards I repeat the same for Servo 2 and after 20ms, because of the interrupt of timer0 the procedure starts again. It works, but I have max. 4ms where I can't get data from the USART (or from an analog input). In your code description the assignment of the potentiometer changes after 1 sec. My idea is more to have something like a joystick where I send data in real time to the Servos, like a remote controlled airplane). Also, you are talking about TimeON and TimeOFF variables. This I don't understand. Isn't the off-time fixed already by the duty cycle (20ms, timer0)? So, if I send, for example, a pulse of 1ms, setting the appropriated Port Pin to Hi and after this periode again to Low, why I do need the TimeOFF variable? Something I still have quite wrong I guess. Sorry for my ignorance Martin
  24. Your advice is very, very helpful, I'm learning a lot. This weekend I try to follow your recommendations and hopefully I'll get there ..... Thanks Martin
×
×
  • Create New...