element14 Community
element14 Community
    Register Log In
  • Site
  • Search
  • Log In Register
  • About Us
  • Community Hub
    Community Hub
    • What's New on element14
    • Feedback and Support
    • Benefits of Membership
    • Personal Blogs
    • Members Area
    • Achievement Levels
  • Learn
    Learn
    • Ask an Expert
    • eBooks
    • element14 presents
    • Learning Center
    • Tech Spotlight
    • STEM Academy
    • Webinars, Training and Events
    • Learning Groups
  • Technologies
    Technologies
    • 3D Printing
    • FPGA
    • Industrial Automation
    • Internet of Things
    • Power & Energy
    • Sensors
    • Technology Groups
  • Challenges & Projects
    Challenges & Projects
    • Design Challenges
    • element14 presents Projects
    • Project14
    • Arduino Projects
    • Raspberry Pi Projects
    • Project Groups
  • Products
    Products
    • Arduino
    • Avnet Boards Community
    • Dev Tools
    • Manufacturers
    • Multicomp Pro
    • Product Groups
    • Raspberry Pi
    • RoadTests & Reviews
  • Store
    Store
    • Visit Your Store
    • Choose another store...
      • Europe
      •  Austria (German)
      •  Belgium (Dutch, French)
      •  Bulgaria (Bulgarian)
      •  Czech Republic (Czech)
      •  Denmark (Danish)
      •  Estonia (Estonian)
      •  Finland (Finnish)
      •  France (French)
      •  Germany (German)
      •  Hungary (Hungarian)
      •  Ireland
      •  Israel
      •  Italy (Italian)
      •  Latvia (Latvian)
      •  
      •  Lithuania (Lithuanian)
      •  Netherlands (Dutch)
      •  Norway (Norwegian)
      •  Poland (Polish)
      •  Portugal (Portuguese)
      •  Romania (Romanian)
      •  Russia (Russian)
      •  Slovakia (Slovak)
      •  Slovenia (Slovenian)
      •  Spain (Spanish)
      •  Sweden (Swedish)
      •  Switzerland(German, French)
      •  Turkey (Turkish)
      •  United Kingdom
      • Asia Pacific
      •  Australia
      •  China
      •  Hong Kong
      •  India
      •  Korea (Korean)
      •  Malaysia
      •  New Zealand
      •  Philippines
      •  Singapore
      •  Taiwan
      •  Thailand (Thai)
      • Americas
      •  Brazil (Portuguese)
      •  Canada
      •  Mexico (Spanish)
      •  United States
      Can't find the country/region you're looking for? Visit our export site or find a local distributor.
  • Translate
  • Profile
  • Settings
Ben Heck Featured Content
  • Challenges & Projects
  • element14 presents
  • element14's The Ben Heck Show
  • Ben Heck Featured Content
  • More
  • Cancel
Ben Heck Featured Content
Forum Engine Management
  • Blog
  • Forum
  • Documents
  • Events
  • Polls
  • Files
  • Members
  • Mentions
  • Sub-Groups
  • Tags
  • More
  • Cancel
  • New
Join Ben Heck Featured Content to participate - click to join for free!
Actions
  • Share
  • More
  • Cancel
Forum Thread Details
  • Replies 63 replies
  • Subscribers 46 subscribers
  • Views 4108 views
  • Users 0 members are here
Related

Engine Management

jack.chaney56
jack.chaney56 over 9 years ago

Hi Ben,

I am a programmer with a very small amount of skill with circuits, and am looking to create a platform for an engine management system, using an Arduino Mega 2560. I had done a bit of the coding, when I ran into some timing issues with the built in Arduino manager, so I switched over and started using AVR Studio and a programmer to go directly to the chip itself.  The code looks like it should work ok, but now I need some additional circuits to handle the energy levels of coils and injectors (Something like IGBTs). Sensors are being run through simple dividers (no protection yet), and cam and crank inputs are through a simple comparitor

 

Let me know what you think,

Jack

  • Sign in to reply
  • Cancel

Top Replies

  • jack.chaney56
    jack.chaney56 over 7 years ago +2
    Back again... After a bit of time away seeking enlightenment (and a steady paycheck), I am ready to get back to work on my project. I have continued to play around with the code and a number of components…
  • jack.chaney56
    jack.chaney56 over 7 years ago +2
    I want to start this thing right, so the shopping list for people that want to play along at home: Raspberry Pi - version is not significant if you don't mind a slow response when using Eclipse, but 3B…
  • jack.chaney56
    jack.chaney56 over 7 years ago +2
    Start off with two things. First, I forgot (neglected) to provide instruction on how to get the compiled code onto the Nano. Fault of familiarity; having done the process so many times, I had shifted to…
Parents
  • jack.chaney56
    jack.chaney56 over 7 years ago

    Start off with two things.  First, I forgot (neglected) to provide instruction on how to get the compiled code onto the Nano. Fault of familiarity; having done the process so many times, I had shifted to auto-pilot. If anyone had not done this before, it is probably a good idea to go over how to accomplish it.

     

    From Eclipse, on the icon bar, there is a button that says AVR with an arrow. This is the "Upload current project to Atmel target MCU" button. Until you configure it, it will complain. First, highlight the project in the window to the left then on the menu bar select Project->Properties then AVR->AVRDude in the Programmer tab, Programmer configuration, click on Edit and select the programmer you are using from the list. The super cheep kind is probably USBasp down toward the bottom of the list. Remember to enter the Configuration name before you say OK, and ok your way back out.

     

    The AVRDude program looks for an AVR Release so go to Project->Build Configurations->Set Active and choose 2 Release. Then rebuild your project. All set...

     

    Plug the USB for the programmer into the workstation USB port, Plug the 6way programmer onto the Nano programmer pins, and plug the Nano USB into a power source, or the USB of the workstation. Then click on the AVR button on the icon bar and the process starts.  It takes a moment but will return with a status of the operation.

     

    Second, It is always good to have a communication channel to the outside world. The Nano conveniently has a USB serial port built in, and the programming of the Tx/Rx lines is actually quite simple (especially since I have done it on dozens of other systems). The workstation will need software also. I use PuTTY, because it is easy to get, easy to install, portable to other systems, and is free. PuTTY defaults to SSH, so it needs to be configured as a Serial, so click on the Serial radio button. Set the Serial line to the communication port that talks to the Nano (example: /dev/ttyUSB0). This can be found when you plug the Nano into the USB port, then read the device information (on Linux, just run dmesg and it will probably be at the bottom of the list). Then set the Speed to the baud rate in use (the source I am presenting is 19200). Last, Enter a name in the Saved Sessions box and click Save to preserve the settings. When you come back, just click on the entry in the Saved Sessions table.

     

    Now the source... This is a straight forward serial communication implementation. It uses input and output buffering, and runs both input and output as interrupt processes. The advantage is the program can dump the full string into the output buffer, and go back to work, not having to wait for each character to be sent. Similarly, it is not critical for the program to respond to each character and can fetch instructions as a whole when they are sent.

    /***************************************************************************************************
     All code provided is original and developed by Jack Chaney. Any similarity to code existing in
     another location or form is purely coincidental. The code presented caries with it no guarantee
     outside my statements that IT WORKED FOR ME.
     
     If, in the future this code is used in any products, please provide proper recognition for my
     efforts.
     
     Jack Chaney, 2018 Chaney Firmware
    ***************************************************************************************************/
    #include "types.h"
    #define UBAUD_57_6    34
    #define UBAUD_38_4    51
    #define UBAUD_19_2    103
    #define UBAUD__9_6    207
    
    #define BUFFSIZE      32
    
    #define TXI0          (1<<TXCIE0)
    #define UCSRA_INIT    (1<<U2X0)                           /* Timebase for UART 2x clock */
    #define UCSRB_INIT    (1<<TXEN0)|(1<<RXEN0)|(1<<RXCIE0)   /* Enable transmit and receive lines and receive interrupt */
    #define UCSRC_INIT    (3<<UCSZ00)|(0<<UPM00)|(0<<UMSEL00) /* n-8-1 */
    #define COMMSPEED     UBAUD_19_2                          /* 19200 */
    
    static UByte rxBuf[BUFFSIZE];
    static UByte txBuf[BUFFSIZE];
    static volatile UByte rxHed, rxTal, rxSiz;
    static volatile UByte txHed, txTal, txSiz;
    
    bool isComReady(void) { return (rxSiz != 0); }
    
    void initUart(void) {
     UCSR0A = UCSRA_INIT;
     UCSR0B = UCSRB_INIT;
     UCSR0C = UCSRC_INIT;
     UBRR0 = COMMSPEED;
     rxHed = 0; rxTal = 0; rxSiz = 0;
     txHed = 0; txTal = 0; txSiz = 0;
    }
    /*==============================*/
    /*       *** WARNING ***        */
    /*  Do not use these functions  */
    /*     within an interrupt      */
    /*==============================*/
    void putCom(UByte c) {
     if ((UCSR0B & TXI0) == 0) {                              /* output buffer empty and no byte currently being sent */
      UDR0 = c; UCSR0B |= TXI0;                               /* put byte in output port, and turn on the interrupt */
     } else {
      while (txSiz >= BUFFSIZE);                              /* make sure there is room in the buffer, or wait (see warning) */
      cli();                                                  /* turn off interrupts, for safety */
      txBuf[txTal] = c;                                       /* put the byte on the end of the buffer */
      txTal = (txTal + 1) < BUFFSIZE ? txTal + 1 : 0;         /* adjust the pointer */
      txSiz++;                                                /* increment the character counter */
      sei();                                                  /* all done so turn the interrupts back on */
     }
    }
    UByte getCom(void) {
     UByte c = 0;
     if (rxSiz > 0) {                                         /* if there isn't an input byte, just return 0 */
      cli();                                                  /* turn off interrupts, for safety */
      c = rxBuf[rxHed];                                       /* fetch the byte from the head of the buffer */
      rxHed = (rxHed + 1) < BUFFSIZE ? rxHed + 1 : 0;         /* adjust the pointer */
      --rxSiz;                                                /* decrement the character counter */
      sei();                                                  /* all done so turn the interrupts back on */
     }
     return c;
    }
    /*==============================*/
    ISR(USART_RX_vect) {                                      /* interestingly, the interrupt looks just like the runtime */
     UByte c = UDR0;                                          /* fetch the byte from the input port */
     if (rxSiz < BUFFSIZE) {                                  /* make sure there is room in the buffer, but because it is the interrupt, can't wait */
      cli();                                                  /* block the other interrupts, for safety */
      rxBuf[rxTal] = c;                                       /* put the byte on the end of the buffer */
      rxTal = (rxTal + 1) < BUFFSIZE ? rxTal + 1 : 0;         /* adjust the pointer */
      rxSiz++;                                                /* increment the character counter */
      sei();                                                  /* all done so turn the interrupts back on */
     } else { /* Dropped bytes go here */ }
    }
    ISR(USART_TX_vect) {                                      /* this could nearly be a cut and paste, but the buffer names are swapped */
     UByte c;
     if (txSiz > 0) {                                         /* special case for last one out */
      cli();                                                  /* block the other interrupts, for safety */
      c = txBuf[txHed];                                       /* fetch the byte from the head of the buffer */
      txHed = (txHed + 1) < BUFFSIZE ? txHed + 1 : 0;         /* adjust the pointer */
      --txSiz; UDR0 = c;                                      /* decrement the character counter, and put the byte in the output port */
      sei();                                                  /* all done so turn the interrupts back on */
     } else {
      UCSR0B &= ~TXI0;                                        /* last byte out
     }
    }
    /* end of file */

    Same as before, add initUart() to the start up. The main() process can loop to listen for isComReady(), then getCom() and putCom(c); just like you would think.

    • Cancel
    • Vote Up +2 Vote Down
    • Sign in to reply
    • Cancel
Reply
  • jack.chaney56
    jack.chaney56 over 7 years ago

    Start off with two things.  First, I forgot (neglected) to provide instruction on how to get the compiled code onto the Nano. Fault of familiarity; having done the process so many times, I had shifted to auto-pilot. If anyone had not done this before, it is probably a good idea to go over how to accomplish it.

     

    From Eclipse, on the icon bar, there is a button that says AVR with an arrow. This is the "Upload current project to Atmel target MCU" button. Until you configure it, it will complain. First, highlight the project in the window to the left then on the menu bar select Project->Properties then AVR->AVRDude in the Programmer tab, Programmer configuration, click on Edit and select the programmer you are using from the list. The super cheep kind is probably USBasp down toward the bottom of the list. Remember to enter the Configuration name before you say OK, and ok your way back out.

     

    The AVRDude program looks for an AVR Release so go to Project->Build Configurations->Set Active and choose 2 Release. Then rebuild your project. All set...

     

    Plug the USB for the programmer into the workstation USB port, Plug the 6way programmer onto the Nano programmer pins, and plug the Nano USB into a power source, or the USB of the workstation. Then click on the AVR button on the icon bar and the process starts.  It takes a moment but will return with a status of the operation.

     

    Second, It is always good to have a communication channel to the outside world. The Nano conveniently has a USB serial port built in, and the programming of the Tx/Rx lines is actually quite simple (especially since I have done it on dozens of other systems). The workstation will need software also. I use PuTTY, because it is easy to get, easy to install, portable to other systems, and is free. PuTTY defaults to SSH, so it needs to be configured as a Serial, so click on the Serial radio button. Set the Serial line to the communication port that talks to the Nano (example: /dev/ttyUSB0). This can be found when you plug the Nano into the USB port, then read the device information (on Linux, just run dmesg and it will probably be at the bottom of the list). Then set the Speed to the baud rate in use (the source I am presenting is 19200). Last, Enter a name in the Saved Sessions box and click Save to preserve the settings. When you come back, just click on the entry in the Saved Sessions table.

     

    Now the source... This is a straight forward serial communication implementation. It uses input and output buffering, and runs both input and output as interrupt processes. The advantage is the program can dump the full string into the output buffer, and go back to work, not having to wait for each character to be sent. Similarly, it is not critical for the program to respond to each character and can fetch instructions as a whole when they are sent.

    /***************************************************************************************************
     All code provided is original and developed by Jack Chaney. Any similarity to code existing in
     another location or form is purely coincidental. The code presented caries with it no guarantee
     outside my statements that IT WORKED FOR ME.
     
     If, in the future this code is used in any products, please provide proper recognition for my
     efforts.
     
     Jack Chaney, 2018 Chaney Firmware
    ***************************************************************************************************/
    #include "types.h"
    #define UBAUD_57_6    34
    #define UBAUD_38_4    51
    #define UBAUD_19_2    103
    #define UBAUD__9_6    207
    
    #define BUFFSIZE      32
    
    #define TXI0          (1<<TXCIE0)
    #define UCSRA_INIT    (1<<U2X0)                           /* Timebase for UART 2x clock */
    #define UCSRB_INIT    (1<<TXEN0)|(1<<RXEN0)|(1<<RXCIE0)   /* Enable transmit and receive lines and receive interrupt */
    #define UCSRC_INIT    (3<<UCSZ00)|(0<<UPM00)|(0<<UMSEL00) /* n-8-1 */
    #define COMMSPEED     UBAUD_19_2                          /* 19200 */
    
    static UByte rxBuf[BUFFSIZE];
    static UByte txBuf[BUFFSIZE];
    static volatile UByte rxHed, rxTal, rxSiz;
    static volatile UByte txHed, txTal, txSiz;
    
    bool isComReady(void) { return (rxSiz != 0); }
    
    void initUart(void) {
     UCSR0A = UCSRA_INIT;
     UCSR0B = UCSRB_INIT;
     UCSR0C = UCSRC_INIT;
     UBRR0 = COMMSPEED;
     rxHed = 0; rxTal = 0; rxSiz = 0;
     txHed = 0; txTal = 0; txSiz = 0;
    }
    /*==============================*/
    /*       *** WARNING ***        */
    /*  Do not use these functions  */
    /*     within an interrupt      */
    /*==============================*/
    void putCom(UByte c) {
     if ((UCSR0B & TXI0) == 0) {                              /* output buffer empty and no byte currently being sent */
      UDR0 = c; UCSR0B |= TXI0;                               /* put byte in output port, and turn on the interrupt */
     } else {
      while (txSiz >= BUFFSIZE);                              /* make sure there is room in the buffer, or wait (see warning) */
      cli();                                                  /* turn off interrupts, for safety */
      txBuf[txTal] = c;                                       /* put the byte on the end of the buffer */
      txTal = (txTal + 1) < BUFFSIZE ? txTal + 1 : 0;         /* adjust the pointer */
      txSiz++;                                                /* increment the character counter */
      sei();                                                  /* all done so turn the interrupts back on */
     }
    }
    UByte getCom(void) {
     UByte c = 0;
     if (rxSiz > 0) {                                         /* if there isn't an input byte, just return 0 */
      cli();                                                  /* turn off interrupts, for safety */
      c = rxBuf[rxHed];                                       /* fetch the byte from the head of the buffer */
      rxHed = (rxHed + 1) < BUFFSIZE ? rxHed + 1 : 0;         /* adjust the pointer */
      --rxSiz;                                                /* decrement the character counter */
      sei();                                                  /* all done so turn the interrupts back on */
     }
     return c;
    }
    /*==============================*/
    ISR(USART_RX_vect) {                                      /* interestingly, the interrupt looks just like the runtime */
     UByte c = UDR0;                                          /* fetch the byte from the input port */
     if (rxSiz < BUFFSIZE) {                                  /* make sure there is room in the buffer, but because it is the interrupt, can't wait */
      cli();                                                  /* block the other interrupts, for safety */
      rxBuf[rxTal] = c;                                       /* put the byte on the end of the buffer */
      rxTal = (rxTal + 1) < BUFFSIZE ? rxTal + 1 : 0;         /* adjust the pointer */
      rxSiz++;                                                /* increment the character counter */
      sei();                                                  /* all done so turn the interrupts back on */
     } else { /* Dropped bytes go here */ }
    }
    ISR(USART_TX_vect) {                                      /* this could nearly be a cut and paste, but the buffer names are swapped */
     UByte c;
     if (txSiz > 0) {                                         /* special case for last one out */
      cli();                                                  /* block the other interrupts, for safety */
      c = txBuf[txHed];                                       /* fetch the byte from the head of the buffer */
      txHed = (txHed + 1) < BUFFSIZE ? txHed + 1 : 0;         /* adjust the pointer */
      --txSiz; UDR0 = c;                                      /* decrement the character counter, and put the byte in the output port */
      sei();                                                  /* all done so turn the interrupts back on */
     } else {
      UCSR0B &= ~TXI0;                                        /* last byte out
     }
    }
    /* end of file */

    Same as before, add initUart() to the start up. The main() process can loop to listen for isComReady(), then getCom() and putCom(c); just like you would think.

    • Cancel
    • Vote Up +2 Vote Down
    • Sign in to reply
    • Cancel
Children
No Data
element14 Community

element14 is the first online community specifically for engineers. Connect with your peers and get expert answers to your questions.

  • Members
  • Learn
  • Technologies
  • Challenges & Projects
  • Products
  • Store
  • About Us
  • Feedback & Support
  • FAQs
  • Terms of Use
  • Privacy Policy
  • Legal and Copyright Notices
  • Sitemap
  • Cookies

An Avnet Company © 2025 Premier Farnell Limited. All Rights Reserved.

Premier Farnell Ltd, registered in England and Wales (no 00876412), registered office: Farnell House, Forge Lane, Leeds LS12 2NE.

ICP 备案号 10220084.

Follow element14

  • X
  • Facebook
  • linkedin
  • YouTube