Jump to content


  • Content Count

  • Joined

  • Last visited

Posts posted by trossin

  1. 0x39 = 00111001(stop=1)

    0x63 = 01100011(stop=1)


    I forget if the msb or lsb is sent first but assumming that the msb is sent first, the 0x39 could look like 0x63 if the receiver was set up to read 7 bits instead of 8 and was sampling a little too fast. I think it is the LSB first so who knows.


    Your baud rate value of 0xc (12) looks suspect to me. But, I am looking at a data sheet for a 16F874. Most of the baud rate generators have been the same for the newer 16F devices so I'm assuming it is the same for the 16F913. You did not specify a clock frequecy that you are running the chip so it is hard to say what the correct value is.


    I'm not a big fan of low baud rates as all it does is slow down your PIC waiting to send data. 115.2K baud has always worked really well for me with a 20 MHz clock.


    The bottom line is that you should check the data sheet for this part and use the equation or tables provided to check that you selected a proper baud rate.

  2. So it seems like you can transmit to the PC ok but maybe not receive. For fun, maybe try adding a wait for 1 second before entering the while loop. It could be that the hello prints out fine but then when the loop is entered, crud pops out in front of the hello. I'm most likely nuts but maybe there are some fun terminal commands that can cause an insert before the hello was already printed.


    If that is the case that the receive is messed up, you should check your connections to the MAX chip.

  3. I think Reynard is on to something in that your set up is ok but your crystal is really 32768 Hz instead of 3276800. If it was 3.2768 MHz, your baud rate error is only -1.5%. RS-232 can handle about a 5% error if I remember correctly (I did the math a few years ago and am too lazy to do it again).


    Setting SPBRG to 6 would give a baud rate of 32768/(16(6+1)) or 292 which is 2.5% slow for 300 baud. That is if your crystal is 32.768KHz. You could give it a try and see if it communicates at 300 baud. If it does, your crystal is the problem.

  4. Right on Russ!


    Taking 50Hz or 60Hz from the power company is a great way to go. This is done by the power folks to support all the old synchronus motor clocks that are still out there.


    One little secret for success with this technique is to make sure you put the "semi square wave" into a Schmidt trigger input on the PIC. For the 16F87x parts, Port B is cool but on Port A, only A[4] has this type of input. This will protect you from little glitches on the AC line that may happen near the switching threshold.


    You can also use DSP technology and make your own little averager in software where you average the input with a sliding window.

  5. This is not a SourceBoost project but I find it handy to develop SourceBoost projects.




    You only get 96 8-bit samples at the 2.5 Msample/sec rate but the upgrade costs nothing. You will need to program you PIC up with my bootloader if you want to be able to perform future firmware upgrades using the PC side code.

  6. what should i get with Your fw and sw? AN0 and AN1 hangs in the air. on "receive data": enter load address, than "0 bytes received" message - i tried to trigger the AN ports, but nothing happened. when i push the send data or stop buttons, i got a "no response from Break" message. i tried it on my computer's COM1, and with a prolific USB > serial adapter (set to COM2)...


    Since you don't have a cassette tape with 1802 noise on it, the only thing you can do is use the View --> Get Firmware Version menu item. This will send a byte to the PIC and receive one back and display the version of the firmware. You should power up the PIC before starting the application.

  7. Your hardware looks fine but you cable may be wrong. Some cable swap pins 2 and 3. Some do not. For fun, try swapping pins 11 & 12 on the MAX part or 2 & 3 on the connector.


    Are you using the hardware RS-232 serial logic in the PIC or are use using the software version? The hardware requires that you set the baud rate generators correctly. I have some examples on my web site that use the RS-232 hardware in Boost-C. I also have schematics.




    Check out the "Cassette Interface" project and CBLib.zip


    The RS-232 from a PIC has no parity and no handshake control so don't turn them on in your terminal emulator. I just write C++ code on the PC side to talk to serial ports as this way the application can set up the terminal and it doesn't have to be a pain every time you use the thing.


    Good luck.

  8. Ok. I looked at the data sheet for the 16F873A part and see a little snag in that the difference between VRef+ and VRef- has to be 2V to get the 10 bit accuracy out of the A/D. The spec:


    VRef+ : min=Vdd-2.5, max=Vdd+2.5

    VRef- : min=Vss-0.3, max=VRef+ - 2


    So, you can't set VRef- to 4.4V, you have to set it to 3V and loose some bits. If my math works, you are only using 0.6/2.0 of the available range or 30% of the 1024 range or you get 307 steps (1 part/307) which gives a 0.3% error instead of a (1/(0.6/5)*1024) = 0.8% error when using VRef- set to zero. For this application, it hardly seems worth adding two resistors for the VRef- input. The ideal is 0.1% error with a 10 bit A/D. I'm sure you will have much more noise in your system than these errors represent so your "Is it really this easy" solution is the one that makes the most sense.

  9. "This is part of a bigger project, to automatically remote start a generator if/when the battery voltage falls to 24.1V or less. Hence less than 24 V should be academic and > 27 volts simply indicates the battery charge state (ish)."


    I still think the Zener diode solution to your problem is a mistake. Using less bits of the A/D gives you more precision (and this is precision that you don't need) 1 part in 200 is a 0.5% error vs. 5% error with the Zener and you have to spend more money (and you will have a more complex design that will give you fits later). If you really want the most precision read the data sheet and learn about the +- offset adjust for the A/D. With 4 total resistors you can tune it up to get all 10-bits out of the A/D for your desired voltage range. The +- offset inputs allow you to set what voltage corresponds to 0 and 1023 for the A/D. You said you want 24 to 27 so you need 2 resistors to make a voltage divider to scale 27V down to 5V. (scale by 1/5.4 so a 4.4K and a 1K would do that). Then when the input voltage is 27 you get 5V. When the input voltage is 24 you get 4.44V. Now all you need to do is set the + ref to 5V (default or tie a wire to +5) and the - ref to 4.44V. This can be done with a 3.33K and a 1K resitor between +5 and ground. With this done, you should get a full 10-bits out of the A/D for the 24V to 27V input.


    Now the only thing that you need to regulate is the 5V supply. As others have said, you can either ignore this or calibrate it away. Also, you most likely can't find the exact resistors you need so you can calibrate that away as well with software. The input voltage pair look like gain and the second - reference looks like an offset. Take two measurements of different voltages then use the old y=mx+b equation to solve for m and b and you have your calibration done.


    I hope this helps.

  10. Ok. I think you have all lost sight of the real problem which is to monitor the battery voltage. You have a 10 bit A/D. I forget the numbers but I think you care about 20V to 25V but with the simple resistor network it is scaled from 4 to 5V. This is 20% or the range of the A/D. So you only get to use 20% of the 1024 point sample range or about 200 points. if knowing the voltate to within 1 part in 200 is good enough (which it is! [25mV resolution]) then you can close your eyes and just use it the way you were.


    The other way to deal with this is to set the A/D reference negative voltage to 4V and the reference positive voltage to 5V. This way you get the entire 10-bit range in the 4 to 5V range. You can set the negative reference point with a simple voltage divider that scales 4/5. But, I don't think this is worth it.


    I'm done ranting for today. Sorry about that.

  11. I was asked how a pin change makes it to the screen in a private message and I thought others might want to hear my guess at how it works:


    In CPluginData::Start() I add a AddPinVChangeCallBack to cause the IDE to notify this class when one of the desired pins

    changes value. The CallBack function will pass a couple parameters (NULL and i). The i variable is just the Pin Id. I had to go through an external function named MyFunc which then uses a pointer to the class to call the Function PinChanged just passing the parameters through.


    In CPluginData::PinChanged, the value of the pin voltage as well as the two passed parameters come in. Only the voltage and Pin Id are used. In this function some math is done on the data and if a result is determined that warrents the display to be updated, the windows SendNotifyMessage function is called. This function wants the view class, a message ID and two parameters can be sent. The first one is a word parameter and the second is a long. With the standard Win32 compiler settings these both amount to 32-bit integers. In the past, the first one was used for a value and the second was used for a pointer. I pass the Pin Id in the first paramter and the PWM value*10 in the second.


    The function CPluginView::WindowProc catches this message from the data class. I do some simple math and check to see if the value changed from the previous time (to prevent display flashing and to improve simulation performance). If there is a change then I update the member variables and call the functions UpdateData and Invalidate to send redraw messages to the windows event loop which will cause the numbers to be drawn based on their mValue values and for the display to be updated by having window route the message to the CPluginView::OnDraw function.


    Windows message routing is crazy land but it works if you blindly follow existing examples or use what the MFC (Microsoft Foundation Class) code generators in Visual Studio give you.



    If you want to send more than two values, you will have to pack them into an array and pass a pointer to the array with the SendNotifyMessage. The secret here is that your Array must not be on the stack but must be either a global or a member variable as the function that you send the message in will go out of scope (cleaned off the stack) before the message can be read. You can pack your data into a structure as well. Either way you will need to do some typecasting in the WindowProc function to put your data back into your "custom" format.

  12. I finished my first version of a simple 4 channel PWM monitor:




    Download and uncompress BoostPWM.zip and copy Release/TedsPwm.dll to your SourceBoost install directory to use it. The source code and an example (CBPwmTest.zip) are provided. The example is a simple software based pulse width modulation implementation.


    Load the CBPwmTest project and then enter debug mode. Turn on Ted's PWM as well as the Button Block. The default PWM config will work but the Button Block needs to be configured to use port A. Label bit 2 "Up 0", bit3 "Down 0", bit4 "Up 1" and bit 5 "Down 1". Right click on plugins to configure them.


    Start the simulator, click the buttons to see how it behaves. Then, please look at the plugin source code and let me know if I'm doing something stupid or you can think of a better or easier way to get the job done. The graphics are lame but I figured that this is just a start.


    Here is a little description of the plugin operation:


    I should note that I still can't get the call back function call correct so I have to resort to pointing to a static function that then uses a global "this" variable to point back into the class. This is something that I have been trying to get right since I started Window's programming in the early 90's.


    All of the value added code is in PluginData and PluginView. Most of the code is just the stock plugin example code. The PluginData sets up call backs that are called when any of the 4 monitored pins changes value. When a pin changes from a 0 to a 1, the time is saved as a start time. When the pin changes from a 1 to a 0 the time is saved as a change time. When the pin changes back to a 1, the current time is subtracted from the start time to get the cycle width and the change time minus the start time is divided by the cycle with to get the duty cycle. At this point a message is sent to the view class to update the new duty cycle. This cycle repeats as long as the pin keeps wiggling.


    This works well as long as the duty cycle is not 0 or 100% as there are no edges to look at. My work around to this problem was to have a timeout counter that if the pin has not changed, the current value is read and a message is sent with a duty cycle of 0 or 100% based on the value of the pin at that time.


    The message handler in the view class saves the current state of the monitors so that if the new message does not change the state, the display is not updated. This is done to reduce the CPU burden of the plugin and to prevent redraw flashing.


    I'm not sure if I need to turn on and off the callbacks as many times as I do. I realize that I need to do it if a pin connection changes but I'm not sure that I have to do it in response to Stop calls.


    Anyway, I hope this example can be used by others to code up their own plugins to share or at least start some discussions on how to code up plugins.

  13. No. That error rate is horrible. Have you tried slowing down the clock rate of the IIC bus? I'm not familiar with the example code that you used but I wrote code using a bit banging technique to interface to a serial EEPROM and see no errors.


    I would suggest simplifying your set up to just ping (send and have it echo the data back) between two processors and see if you still are having problems. These devices also have hardware IIC machines in them so I'm not sure if you are using the PIC's logic or bit banging.


    Good luck.

  14. A pure scope won't do the trick as the output of the PIC is a digital signal with variable pulse width. It seems that you would need a plugin that can display the duty cycle of a continuous waveform. I don't know of one but it does not seem that it would be that hard to code up. It would just create call backs on a particular pin changing and measure the amount of time between the high and the low and display the ratio of high/(high+low) or 1 minus if the drive signal is active low.


    Without such a plugin, you could simulate using a device with extra pins and use those extra pins to display the control value on a plugin. The Stop Watch plugin may give you some feedback as it will display the width of a pulse on a single pin (use repeat mode instead of one-shot).

  15. I've made some progress on my problem and was able to get the active low push buttons to work by adding SetOutputState(1) calls to the CPluginData::Start() function. The only problem now is that this does not work for port A.


    I uploaded an example plug in with a button on port A bit 2 and port B bit 0 to show the problem. It along with an example SourceBoost project can be found on my web page here:




    Or right here:




    To reproduce the problem:


    1. Either build the Visual Studio project (which will copy plugin.dll to c:\Program Files\SourceBoost\BoostDigIO.dll) or copy release/plugin.dll to your SourceBoost install.
    2. Start up SourceBoost and load the CBButtonTest project
    3. Enter debug mode
    4. Turn on the BoostDigIO.dll plugin (there is no port config. It will use the two bits I described above). An 8-bit counter will start counting in the plugin window to show that my timer interrupt is working (I use it for sampling output for my Nixie tube plugin). Do not click any of the push buttons!
    5. Turn on the LED Block plugin and configure it to use port C.
    6. Hit F5 to start the debugger.
    7. Notice that the LED block shows the value 0x01 then look at the code. It should display 0x81 since neither of the buttons are pressed.
    8. Click and hold down then release the RB0 Pin button. Notice that the LED block displays 0x00 when the button is held down and 0x01 when it is released.
    9. Do the same for the RA2 Pin button. Notice that pushing the button the first time has no effect but on release, the display shows 0x81 and from then on the button works correctly.


    Adding the following code to void CPluginData::Clk( long clk ) works around the situation if you define MAKE_PORTA_WORK at the top of the file.


    void CPluginData::Clk( long clk )
    #ifdef MAKE_PORTA_WORK
    // Have to pulse the state low to see a change
    if(clk>90 && clk<100){
    // Only needed if button state not managed in view class
    if(clk>100 && clk<110){


    The reason for the final drive to 1 is because in the view class, I only update the button state if it has changed.

    If you look at the source code for the plugin, you should see that I treat both buttons the same. The only difference is that one uses port A and one uses port B.


    My theory is that port A is not configured as a digital input until a few cycles into the execution of the PIC simulator because by default it is configured as an A to D channel. It could be that the simulator gets the state as 1 at the start but when the pin is reconfigured due to the PIC program, the voltage value on the pin is not maintained. As always, this is just my guess. I put the code out there so that mistakes can be pointed out or cleaner solutions suggested.


    For my Nixie tube plugin, I had to use a larger value for the times that I applied to the fix as it depends on how much start up code (array initialization) is executed before main is called. So my work-around is a little icky.


    I have a few other general questions for plugins:


    1. Is there a naming convention that should be used for user shared plugins? For example, the author could put their name (or Forum name) in the title trossin_NixieTube.
    2. I have 11 little images used for my Nixie tube plugin. Is there a way from the plugin to figure out the install path to be able to load the files. I tried using the current directory and found that I had to specify the full path to load the files. I would like to stick them in a sub-directory (any idea on names? I was thinking {PluginName}Data.
    3. Any interest in user supplied plug in hosting by SourceBoost or should this stay outside the company so complaints don't become a bother?


    Thanks for the help.

  16. Thanks Dave,


    Lots of good magic there! I'll give it a try and report back.


    I'm a big fan of coding up custom plugins and believe that anyone with a little windows programming experience should give it a try as they really enhance project development.


    Thanks for opening up the API.


    Here is a screen shot of my Nixie tube clock plugin (it seems that you have to click the image below to see it):



  17. One of the nice features of PIC processors is the internal pull up resistors on port B. This allows easy connection of a push button to ground but the code must look for a zero for a press instead of one. The plug-in push buttons are active high so I usually use them in 2-state mode and push them in for not pressed and push them out for pressed. This is ugly an makes my code think the buttons are pressed at start up, so I tried writing my own active low push button plug in. I did not get fancy, so it drives 5V when not pressed and 0V when pressed through a low impedence driver. It works fine except for one nagging problem.


    At start up, the PIC simulator sees the button as a zero instead of a 1. I hooked an LED plugin to port B and it shows that my button simulator is working correctly and is driving a 1. I have to click the button (drive to 0V) then let go of the button (drive to 5V) in order for the PIC code to see a logic 1. I tracked it down as far as waiting for clock cycle 1000 and then driving 0V (like pushing the button)


    void CPluginData::Clk( long clk )








    I feel that I'm missing some magic call that needs to be made to make the initial state a 1 and not a zero. Without the above code, once I click my button and get it working, I can reset the simulator and it works fine. It only fails just after entering debug mode.


    Anybody have some secrets?


    I'm currently working on a PIC based Nixie tube clock that uses images of the tubes lit with different numbers to emulate the display. It looks really cool but my buttons don't work as desired. Once I get this all working, I'll post the source on my web page.

  18. I think Renard left out a subtle point in that most libraries need not only a .lib but also a .h which defines the function prototypes that the library contains. Then, the user of the library would also include the .h file in the source that is using it so that the compiler knows what to expect. This is the same as if you have multiple files in a stand-alone compile.




    char ScanKeyMatrix(void);





    #include "KeyLib.h"



  19. Is this what you are looking for?


    void InitADC(void)
    adcon1 = 0x0e;	// (left justified) 1 A/D channel
    adcon0 = 0x81;  // FOSC/32, channel=0, ADON=1
    unsigned char SampleADC(void)
    set_bit(adcon0,GO);  // Start conversion
    return(adresh);		// Fetch high 8 bits of result

  • Create New...