Jump to content


  • Content Count

  • Joined

  • Last visited

  • Days Won


Everything posted by Orunmila

  1. To get to your e-mail notification settings, go to your profile menu (which is top right corner) and select "Account Settings". On the overview tab there is a menu on the right called "Notification Settings". Under this you can manage notifications. You should be able to get to the menu from this link: https://www.microforum.cc/notifications/options/ EDIT: Also since this was hard to find I added a menu item under the "Activity" menu so you can get to this more easily.
  2. If you click on your profile (which you can do by clicking on the image or in the menu at the top right) you will see a circle with the first letter of your name on it, that is the default profile picture. In the left bottom corner of the picture (when in your profile view) there is a little icon you can click on to change the image.
  3. Just for fun, here is a video of the mill in action. IMG_8228.MOV
  4. Creating the sine waves is fairly easy, I usually do that with a sine lookup table and simply having 3 index variables indicating where each phase is, you then simply copy the PWM DC value to the PWM register on a regular interval, like a timer interrupt. But as always the devil is in the details. You have to do something different if the motor is sensorless, eg. as measuring the back-emf while driving it becomes a challenge. I recently did a 3-phase brushless DC motor project for a friend (we built a grain mill for him to make beer - important stuff! ). The motor was sensored so it was drop off a log easy, had it been sensorless it would have been much more of a challenge. We simply drove the coils with square waves and adjusted the power on each wave by driving it PWM. Since motors have lots of inductance the currents in the coils end up being pretty sinusoidal as it makes a great filter on your square wave signal. We never measured the exact torque, but we added a PID controller and it now runs at 70 RPM (the video shows around 3000 RPM peak) and it is not possible for 2 people working together to stop that motor from spinning it has so much torque! So if you can give us some more info about the motor, is it BLDC, is it sensored or sensorless, etc. We can be of more help 🙂 Here is a video of the motor spinning with that method (it is a Fisher and Paykel direct drive washing machine motor). IMG_7256.MOV
  5. It would be interesting to know what you will be driving with this, and which device you are planning to use. It will also help to know what the frequencies should be, number of etc. There are some interesting ways to do this, with new devices such as the K42 family it is possible to set up DMA to bang out the signals for you while the processor could even be sleeping! If you are driving a motor it may also be interesting to look at third harmonic injection, saddle wave PWM's or space vector modulation to get maximum power out of the system. Have you settled on a device to use or is this still wide open? This btw. is SVM from an old 2005 Microchip Application note for a dsPIC (AN1017)
  6. Reputation on the site is earned by the number of posts you make as well as the reaction of members to your posts. It is not possible to get negative points, but you will have to post good content in order to get approval by other members. Every member can only react to a post once and you cannot react to your own posts. If you look at a member's profile you will see both the content count and the reputation level listed, there is a global leaderboard showing members with the most content as well as reputation. Based on the number of content items you have posted you will earn a Site Rank. Ranks are assigned as follows: Content Count Rank Indicator 0 User No Indicator 1 Newbie 10 Pupil 50 Contributor 100 Teacher 500 Expert 1000 Candidate Master 5000 Master 10000 Grand Master You will also earn Group promotions based on a combination of your reputation, your content count and how active you have been on the site. When you are not logged in your group will show as "Guest". Guests have permission to see posts but cannot make any posts. All new registered users will start out as "Member". As a "New Member". This group has some restrictions e.g. they will not be able to post HTML, cannot upload attachments and cannot create polls or edit other member's content. As you gain more reputation and tenure on the site you will gradually be promoted to higher groups with more rights, up to the level of Moderator where you will be able to perform most administrative actions on the site. Currently the groups configured are as follows: Group Name Requirements New Member New Members start here. Posts have to Moderated before publication. Member Automatic promotion to "Member" after earning +5 Reputation AND +5 Content Posts Elder Promotions made by Moderators on discretion Moderator Promotions made by Moderators on discretion We will also establish an indication of community reputation based on the upvotes and reputation your content has received on the site. This will be shown as a colored band on your profile. We are working on adding badges for reputation, we will see how that works out 🙂
  7. A lot of people use printf and sprintf quite a lot without thinking how it actually works. The problem here is that the format string is interpreted at runtime, but the parameters are passed in with specific data types. If you look deeper into the specification for these functions you will find that the relationships between the data types in your format string (e.g. %d) to the parameters you are passing through after the format string is purely by agreement and the compiler cannot convert the variables to the correct type automatically at compile time. The conversion rules for printf (and sprintf) say that every parameter passed into the function in the variable argument list (that is after the comma) shall be subjected to integer promotion, which means that it will be increased in size at least to an "int". The size of an int would be different depending on the architecture or device, but it will always be at least 16-bits (as the C standard requires the int type to be at least 16-bits - even if the processor is only 8-bits) After this the parameters are packed next to each other in memory as a raw data block, and the printf code will unpack it again assuming that you followed the agreement of passing the correct data types. What happened in the code in the question above is that the constant used to multiply with was a 32-bit value, which means that we passed 3x 32 bit values into printf. So the raw data block looked like this: 32-bit 32-bit 32-bit 0x00000032 0x00000046 0x00000050 But the sprintf function is expecting 3 x integers which are on this platform 16-bits in size, which means that it is interpreting the data as we specified which is 3x 16bit integers: 16-bit 16-bit 16-bit 0x0032 0x0000 0x0046 Of course the next integers would be 0x0000 followed by 0x0050 and then the last 0x0000. The order of these are such because of the order the bytes are stored within the number (little endian, which means the lowest byte has the lowest address). If we used %ld instead the printf function would have interpreted the data correctly of course, so always make sure you use the correct format specifiers which match your parameters exactly, the compiler is not going to check this for you - it is your responsibility! When you are on a 32-bit processor where an int is actually 32-bits it is very easy to get this right by accident as everything ends up being converted to a 32-bit parameter, but you should still take care. Sometimes we use larger data types and often our code needs to be ported to other devices and this can easily become a hard bug to track down if you are not aware of these mechanics.
  8. I am seeing weird behavior when I am using sprintf with my code, the code looks fine but it is printing junk! Here is an example program for a PIC16F18875 : #include <xc.h> #include <stdio.h> #include <stdint.h> char buffer[128]; void main(void) { uint32_t multiplier = 10; sprintf(buffer, "Value1 : %02d, Value2 : %02d, Value 3: %02d", 5*multiplier, 7*multiplier, 8*multiplier); NOP(); } The resulting string printed is this: Value1 : 50, Value2 : 00, Value 3: 70 Why is this happening?
  9. If you use the __builtin_software_breakpoint() compiler built-in function and look at the list file generated by the compiler you will see that it translates the instruction (0x003) as "trap" - this instruction is not documented in the device instruction set or datasheet, but it easy enough to discover by looking at the lst file. 1211 1212 ;main.c: 17: __builtin_software_breakpoint(); 1213 07F1 0003 trap 1214 1215 ;main.c: 18: __nop(); 1216 07F2 0000 nop 1217 ...
  10. Ahhh yes, that is very misleading! So this is what that means. When you are using MPLAB-X and you are setting breakpoints using the IDE then the PK3 is not able to use software breakpoints to fulfill these requests for having a breakpoint. On the other hand, if you use the __builtin_software_breakpoint() as I showed above this is not covered by that statement and even the PK3 will happily break when it hits the instruction. This is achieved by jumping into the breakpoint code of the debug executive on the device.
  11. I recently started using Software Breakpoints as well, very useful feature which not many people know about! You can do that like this : LATA = 0x00; __builtin_software_breakpoint(); // This will add a swbp instruction which will stop on the following line NOP(); // I like using a NOP here, makes things simple, but it is not required LATA = 0xFF;
  12. There is actually a lot of information on this in the Release Notes for the compiler and also in the XC8 Compiler Users's Guide. MPLAB_XC8_C_Compiler_User_Guide_for_PIC.pdf This has also been a very interesting resource on how the compiler can be used more effectively on embedded projects. MPLAB® XC8 USER’S GUIDE FOR EMBEDDED ENGINEERS.pdf
  13. I came across this and thought I would post it here in case others hit the same snag. In the past it was possible to hard locate a variable using XC8 like this : volatile unsigned char TMR0 @ 0x01; Although this was convenient it was also not strictly acceptable C syntax, so if you were using a linter on your code to check if you have anything untoward in there it could flag this as being incorrect C syntax. In XC8 v2.0 the syntax was switched to what Microchip calls the CCI (Common Compiler Interface) syntax, which uses the following syntax to hard locate a variable. volatile unsigned char TMR0 __at(0x01); Since this has a double underscore and the brackets it is more compliant to the C standards. With XC8 2.0 it is possible to compile your old code using the @ syntax if you set the compiler settings to use "C90" format. The setting looks like this, it is under "XC8 Global Options" and is called "C standard". If you want to use something which does not use a compiler specific extension such as @ or __at() you can always do it like this: // This defines the TMR0 register - volatile is important to tell the compiler that this is a volatile register, // read more about volatile in the XC8 Users Guide #define TMR0 (*(volatile uint8_t*)0x0001u) // You can now access it like normal, something like this. TMR0 = 0x12; Hope that helps 🙂 There are a couple of other CCI keywords which are described in the compiler user's guide such as __interrupt which you can also get to work by switching back to the pre 2.0 syntax by choosing "C90" as shown above. I also posted about this on the Microchip forum on this thread. Below is a copy of that post. 8<-----8<-----8<-----8<-----8<-----8<-----8<-----8<-----8<-----8<----- Hi Guys here is the full story:With XC8 2.0 we are very excited that we get an improved compiler front-end, which brings things like C99features to us which we are very happy to have. Unfortunately pre-XC8 2.0 we had some keywords in the compiler which were not strictly conforming to the C standard. Keywords like these: Using "bit" as a variable type Using "interrupt" to mark interrupt functions Using "int i @0x88" to hard locate a variable at a ram location Using "#asm" to create inline assembly. Together with the wonders we get with the new front-end we have also lost support for the "old" way of doing these things which was not strictly standards compliant. XC8 has for a while allowed the corrected syntax but with 2.0, due to the improved front-end implementation, these non-standard keywords are no longer available. Unfortunately MCC has been using too many of this pre-XC8 2.0 syntax and this can now cause some compatibility issues. To minimize problems the IDE will default any "old project" you open (and change the compiler to XC8 2.0) to pass in "C Standard = C90" which can be set under "XC8 Global Options". This will tell the compiler to use the pre-XC8v2.0 front-end to compile your code which should give you the same behavior you got before with XC8v1.45 and earlier. If you use MCC with this project you should experience no problems. When you make a new project it will default to "=C99" which means the deprecated syntax will cause compilation errors where the above syntax was used. You can get these projects to work easily by either fixing the code to use the standards-compliant CCI syntax - or changing the define to C90 and leave the code unchanged (leaving the problem for later so to speak) The correct syntax is (the underscores are all double-underscores btw.): "__bit" for the "bit" type "__interrupt()" instead of just "interrupt" - yes the brackets are required. To hard locate a variable use e.g. "int i __at(0x88)" For inline asm use "asm()" There are also a couple of small issues which should be resolved in the next compiler release. These are: The int24_t type define in stdint.h is not present for C99 mode, it will be there soon. There is a change in the Vectored Interrupt vector names which we are still looking into, contact me if you run into this one and I can help. We have released a new version of the MCC 8-bit libraries which will addresses these issues by converting the code to CCI compatible syntax which will make it work on all modes and versions of the XC8 compiler. This can be downloaded from microchip.com/mcc. The first version of the libraries with the update is v1.75
  14. When you make a pin a Digital Output this means that you are going to use the pin as an output and when you read data back from the pin you are expecting to read back from the LATx register the values you are using to control the port with. In most cases you do not want to actually read the pin values back or you can trip yourself up with Read-Modify-Write problems. What MCC is doing here is simply disabling all reads from the I/O Pins. This means that when you write to the port and the pin transitions this transition is not detected by the input circuitry and this is not propagated through the device, which of course will save you some power as each time a bit flips this consumes some small amount of power, so MCC is trying to help you here. There may be one exception where you want to go change the pin to not have "Analog" checked, and that is if you plan to read back the value of the PORT register to see if there is a short circuit on the pin or if the pin is overloaded so much that even when it is trying to drive a 1 the voltage is low enough to be detected as a 0. If you are using reads of the outputs like this to detect errors then you will want to uncheck Analog, in all other cases it is actually better to leave it checked! Here is the pin diagram (from the Datasheet). This clearly shows that all ANSELx is doing is forcing the input to always read 0. Note that regardless of the ANSELx value, the pin voltage will always be routed to the Analog Peripherals e.g. Comparators or OpAmps, so ANSELx has no relation to Analog inputs!
  15. The best way to start this is to show the pin diagram from a device datasheet. I captured this from the PIC16F18875 datasheet from the chapter on I/O Ports. The operation is described in the datasheet as follows From this diagram you will see that when you write to LATx or when you write to PORTx the value will be "latched" into the D Flip-flop, so upon writes it seems very similar. There are actually 8 of these circuits per port, and modifying port data is often done one pin at a time, which gives rise to one of the most common problems on PIC microcontrollers, the "Read-Modify-Write" problem. This happens when you have code like this to set a single bit: PORTA |= 0x01; // Set the lowest bit (0) on the port The problem with this is that the PORT is read first, and then the resulting read is modified and written back to the port. Now if you look carefully at the circuit above you will see that when we read the PORT register we will be reading one of 2 values. When ANSELx for the pin has been set to a 1 the reading of the pin is disabled and the value we read from PORT will always be a 0, even if the pin is currently an output and we are driving it high! This means that code like the line above will try to set only the lowest bit on PORTA, but it may accidentally turn other outputs low by accident due to reading a 1 on those outputs when I have ANSELx as a 1. (btw. The purpose of ANSELx is to disable reads on pins that we know will be carrying analog voltages. For input pins carrying a voltage between a 0 and a 1 can cause excessive power disappation by the pin and this should be avoided, so do use ANSEL when you know the pin will be floating!) The other possibility is that ANSELx is set to a 0, in which case we are reading the actual voltage on the pin. The problem here is that if we are e.g. driving a high current LED the port voltage may actually sag so low that reading it back would not give us a 1, or there may just be noise on the pin, or it may be shorted to GND, either way we will be accidentally changing the outputs of other pins because we are reading the PORT. Having a seperate LATA register allows us to completely avoid this problem! So now reading from LATA will NOT read what is on the pin and will be unaffected by the setting of ANSELA on the pin. As you can see from the diagram reading from LATA will simply read back what is in the D Flip-flop and be unaffected by what is going on at the physical pin. This means that doing the or to set a bit will be guaranteed to only affect that pin. Here is another example of the problem (you can even run this in the MPLAB-X simulator to see what happens. If you do that you should create watches on PORTA and LATA, and you will see that no matter what you do PORTA will always be 0x00, and LATA will behave as described in the comments: ANSELA = 0xFF; // We disable reads on all pins on PORTA LATA = 0xFE; // Write all the pins except for LATA0 to a 1, LATA0 = 0 LATA |= 0x01; // Set LATA0 to a 1, now all port pins are high. PORTA |= 0x01; // Here we attempt to force the lowest pin on PORTA to a 1, but by // accident we are setting all the other pins to 0 !! // At this point LATA = 0x01 and PORTA = 0x00 (as it always reads 0x00 due to ANSELA being all 1's) Summary So in summary the purpose of the LATx registers is to allow us to easily mask bits into our output ports without having to worry about read-modify-write problems. A general rule of thumb is to always read and write the LATx registers if you are trying to manipulate outputs on a PORT and always read the PORT registers only in the case where you are trying to get the digital input values of the pins on the port.
  16. I was wondering if any of you have some ideas why we still see so many people using the PIC16F877 and the PIC16F877a for their projects? I can imagine that many schools and universities have programs that were based on this very old device but surely these guys must be updating their material from time to time? Today I would expect people to use something like the PIC16F18855 or something like that. The XPress evaluation board for that device is just $13 on Digikey ( link to Digikey ) and it does not even require a programmer to program the board (it has drag and drop programming via USB - the board shows up as a hard drive MSD device). Actually I think the PIC16F18875 is a better comparison as it has the same number of pins (40). So is any of you using the PIC16F877 and if so why that device? Just for the discussion here is how the devices stack up, with all the peripherals and extra RAM on the newer device I really cannot see how it makes sense to use the 877! What do you all think? PIC16F877 PIC16F18875 Digikey 1-off price $5.09 $1.67 Max Speed 20MHz 32MHz Flash 8k x 14 8k x 14 RAM 368 x 8 1K x 8 Package 40 PIN DIP 40 PIN DIP I/O Pins 33 36 Operating Range 4V-5.5V 1.8V-5.5V EEPROM 256x8 256x8 Peripherals CCP(2), MSSP(1), USART (1), TIMERS 8/16(2/1), CMP (2), ADC 10b(8 channels) CCP(5), PWM(2), MSSP (2), USART (1), TIMERS 8/16 (3/4), SMT Timer(2), ADCC 10b(35 channels), CLC (4), DSM(1), NCO (1), ZCD (1), CRC (1), CWG (3), CMP (2), DAC (1), VREF,
  17. Saw this on Hackaday today - nice to be able to connect to the cloud using an 8-bitter like this! https://hackaday.com/2018/10/27/new-avr-iot-board-connects-to-google/
  18. Did you guys see the new XPress Evaluation boards that Microchip are now selling. These boards are very cheap and pretty cool way to start. They do not need any programmer to get going (programmer is on-board) and they also implement a USB CDC interface so you can hook up printf to go to the serial port and get a console on your device going. If you are using MCC you can set all of this up without writing a single line of code! Pretty cool beginner board I think and they are going for $12 with an additional $3 discount running right until the end of 2018 ! The boards look like this : You can get them from Microchip Direct here : https://www.microchipdirect.com/product/search/all/DM182026
  19. I am going to pin this post here in the Forum Help area for discussions on what members like or dislike about the setup of the site. We are limited by the capabilities of the forum software we use, but it is fairly flexible and we are trying to create a community where we have it configured the best way possible. If you have any feedback please do post it over here so that we can investigate and see if we can improve it.
  20. Ok, so every time I set up a pin as an output MCC insists on making it "Analog". It looks like this setting has something to do with the ANSEL register, but surely an output is not Analog so why do they do this?
  21. I think this is probably the most common question we get from beginners. Everybody gets confused with LATx and PORTx and run into Read-Modify-Write issues, so how does this really work?
  22. I have a bunch of old projects using the @ method to hard locate variables at a specific location in data memory, but since I upgraded to XC8 2.0 none of these are working any more! How do I do this with the latest compiler? I am using XC8 v2.xx. I also saw this error at my interrupt service routine and I suspect that this is the same problem. My interrupt code looks like this void interrupt my_isr(void) { ... my code here } error: variable has incomplete type 'void'
  23. The easiest way to see all posts tagged with a particular tag is to just click on the tag in any post tagged with it. If you are trying to search for a tag or set of tags you can also do this under the Activity tab. The last sub-menu will be the advanced search. Under advanced search there is a menu called "+Search by Tags", click on that and you can enter the tags you want to find. It should look like this: When you click on Search By Tags you can enter tags by typing the tag text separated by commas or just hitting "tab" in between each tag. It should look like this :
  • Create New...