SPI question

Posted on
Page
of 2
/ 2
Next
  • I am trying to write code to connect a chip to the espruino but am really not getting how it works! I want to figure it out on my own but need some help. Hence the fact I am not stating what chip I am trying to interface too.

    The chip has three lines SCK, MISO, and CS.

    So I connect SCK to B3(sck on espruino), MISO to B5(miso on espruino)

    CS is connected to C0

    In the command line I write the following commands
    ///

    SPI1.setup({ mosi:B5, sck:B3, baud:1000000 });
    =undefined
    SPI1.send(0b00000,C0);
    =255

    ///

    The device should send back a 32 bit number.

    From my understanding reading the datasheet once the cs goes low the chip should start writing data to the espruino as the sck signal starts. Can anyone offer some pointers or explain the error in my understanding of SPI.

    Thanks.

  • I think there are two main issues here:

    • In SPI, MISO = Master In Slave Out - so you just have to connect MISO on the chip to MISO on Espruino (and you've connected to MOSI, which is an output on Espruino). Try using B4 instead.
    • SPI.send sends only 8 bits, regardless of the number you put in. Instead, you'd have to send 4 sets of 8 bits and recombine them: var d = SPI1.send([0,0,0,0],C0); result = (d[0]<<24)|(d[1]<<16)|(d[2]<<8)|d[3];

    Otherwise it's doing what you expect - C0 will be taken low, data clocked in/out, and then C0 is taken high again.

  • Thanks Gordon. I now am receiving data. The chip was a Max 31855 used to measure thermocouple temperature. I will share code to add to modules when I have it working.

  • Strange I had it working for about 1 minute and then it stopped working. I hooked up a logic analyzer and it does not send 32 clock cycles. Seems to send a few then stop and then send a few more. I know the chip is working as I am also running it on a different kind of micro controller.

  • How exactly is it not working? It's unlikely that something would have just happened after 1 minute... are you sure it's not just a bad connection?

    I just checked and it seems that at 1mbps it's having trouble keeping the 1 byte SPI buffer full. To be honest it shouldn't really be having problems with that - I'll have to look into why.

    However I'd be very surprised if that was the problem. That's why there's a clock and a CS line after all.

    If you do really want an unbroken clock signal your other options are to just lower the baud rate (500000 seems to work fine) or to switch to sending/receiving Strings, which are a bit faster to access:

    var d = SPI1.send("\0\0\0\0",C0); 
    result = (d.charCodeAt(0)<<24)|(d.charCodeAt(1)<<16)|(d.charCodeAt(2)<<8)|d.charCodeAt(3);
    
  • I have confirmed that the 32 clock cycles are now sent on the sck line. The CS line is also working. However the MISO line reports all 255's which is not right. It's not the chip so something strange going on. I will try to get the STM discovery upgraded to report if it has the same behavior.

  • Just uploaded for arran:


    1 Attachment

    • 606C9109-A32E-4798-A377-78A462A132B0.png
  • Have you updated the SPI initialisation code to initialise B4 to miso? In the original code you gave, you don't do that.

    If you specify some SPI pins but not others, only the SPI pins that you specify get set up - and if you don't specify an input then it'll probably just read 1s in - regardless of what the actual input is doing.

    In the graph you sent, I don't see any data coming from the chip. Is that intentional?

  • If the chip isn't sending data, is it that it's expecting a 5v signal? That shouldn't be an issue, but I'm struggling to see what the issue could be.

    Also you said that it was originally working with Espruino, and then stopped?

  • Finally got it to work!

    Not sure what the problem was as I unsoldered everything and reassembled it. I was able to get output from the chip if I connected the logic analyzer to the pin of the chip before I disassembled. So I suspect it was a dry joint or something hardware related. Gordon thanks for your help. Will send you the code to add to modules when it is completed. Next job is to add a pressure transducer to the board.

  • Gordon,

    Thanks for your help.

    Here is the code to interface espruino to a max31855 chip. The max31855 is connected to a thermocouple to measure high temperature up to 1300C. Feel free to use it to create a new module for Espruino.

    
    //setup SPI port
    SPI1.setup({ miso:B4, sck:B3, baud:1000000 });
    
    function getTemp() {
      //send command to get 32 bit word back from max31855
      var d = SPI1.send("\0\0\0\0",C0); 
    
      //calculate probe temperature
      eTemp = (d.charCodeAt(0)<<6 | d.charCodeAt(1)>>2)*0.25;
    
      //check for fault codes
      if (d.charCodeAt(1) & 1)  {
          fault = (d.charCodeAt(3) & 7);
    
        switch (fault) {
          case 1:
            console.log("No probe detected");
            break;
          case 3:
            console.log("Probe shorted to Ground");
            break;
          case 4:
            console.log("Probe shorted to VCC");
            break;
          default:
            break;
    
    
      }
      }
    
      
      
      else {
      //Print temperature
    
      console.log("EGT = "+eTemp + " C");
      }
    }
      setInterval(getTemp, 250);
    
    
  • Modularized.

    I posted the module - does this work?

    SPI1.setup({ miso:B4, sck:B3, baud:1000000 });
    var max=require("http://drazzy.com/espruino/MAX31855.js").connect(SPI1,C0);
    
    console.log(max.getTemp());
    
    

    Module code:

    exports.connect = function(spi,cs) {
      return new MAX31855(spi,cs);
    };
    
    function MAX31855(spi,cs) {
      this.spi=spi;
      this.cs=cs;
    }
    
    MAX31855.prototype.getTemp = function () {
      var d = SPI1.send("\0\0\0\0",C0); 
      var trtn={};
      trtn.temp=(d.charCodeAt(0)<<6 | d.charCodeAt(1)>>2)*0.25;
      if (d.charCodeAt(1) & 1)  {
        var fault = (d.charCodeAt(3) & 7);
        switch (fault) {
          case 1:
            trtn.fault="No probe detected";
          case 3:
            trtn.fault="Probe shorted to Ground";
          case 4:
            trtn.fault="Probe shorted to VCC";
          default:
            trtn.fault=fault;
        }
      }
      return trtn;
    };
    
  • @DrAzzy: just a little code review question: why do you store this.spi / this.cs inside the constructor? And why not use this.spi / this.cs in the getTemp?

    I would have expected this:

    MAX31855.prototype.getTemp = function () {
        var d = this.spi.send("\0\0\0\0", this.cs);
        ...
    }
    

    Otherwise i don't understand the constructor.

  • Nice, thanks both of you!

    I've got an Espruino car ECU project and I always wanted to be able to log the exhaust temperature. It glows cherry red so it'd melt most stuff - I'll have to have a look at this and see if I can rig something up :)

  • @possmann: I think it might have been a mistake :)

  • I saw your trig code and figured it was engine related.

    I actually wrote this code to measure engine exhaust gas temperature. You can buy temperature probes that are designed to work for this application

    search type K EGT on ebay and you will find them for about $15.

    I picked up a pressure sensor to measure turbo boost pressure. That sensor has a 0 - 40mv voltage swing from 0 - 29 psi. I now realize I should have looked harder to find one that had SPI or I2C interface as it would be easier to interface.

  • You could just look in a scrap yard? I'm measuring vacuum, but the GM sensors are great. 5v in and a basically 5v swing on the analog output. I'd guess the ones off turbo cars are very similar

  • Thank you for putting this code into a module. I have been trying to understand OOP Javascript and just brought a book to try to wrap my head around it. Looking over this code as well as the comment from possman, It now fairly clear the way it works. Having scratched my head over this for a couple of weeks and now the light bulb in my brain turns on!

    I did try the code and it partially works. It does report temperature correctly but the error reporting does not work correctly now. It only reports case 4 under all fault conditions. I will try to debug this and repost code later today.

  • I have a old VW TDI that I have been experimenting with. Interestingly from my research they don't have a turbo pressure boost sensor, if they had it would be easiest just to tap directly into the sensor or the CAN network. It think that they calculate boost pressure using RPM and mass air flow sensor.

    Ideally the easiest way to do this would have been to connect to the CAN and get boost pressure if VW had a boost sensor on the motor. I was able to do this on a Caterpillar large diesel engine using javascript and npm Can on a Beaglebone Black.

  • This seems to have fixed the fault reporting issue.

    
    
    exports.connect = function(spi,cs) {
      return new MAX31855(spi,cs);
    };
    
    
    function MAX31855(spi,cs) {
      this.spi=spi;
      this.cs=cs;
    }
    MAX31855.prototype.getTemp = function () {
      var d = this.spi.send("\0\0\0\0",this.cs); 
      var trtn={};
      trtn.temp=(d.charCodeAt(0)<<6 | d.charCodeAt(1)>>2)*0.25;
      if (d.charCodeAt(1) & 1)  {
        var fault = (d.charCodeAt(3) & 7);
        switch (fault) {
          case 1:
            return trtn.fault="No probe detected";
    
          case 3:
            return trtn.fault="Probe shorted to Ground";
     
          case 4:
            return trtn.fault="Probe shorted to VCC";
     
          default:
           return  trtn.fault=fault;
        }
      }
        else{
    
      return trtn;
        }};
    
    
  • Oh, I see. I was doing switch/case wrong, and left out the breaks. I always forget the syntax for switch/case.

    exports.connect = function(spi,cs) {
      return new MAX31855(spi,cs);
    };
    
    function MAX31855(spi,cs) {
      this.spi=spi;
      this.cs=cs;
    }
    
    MAX31855.prototype.getTemp = function () {
      var d = SPI1.send("\0\0\0\0",C0); 
      var trtn={};
      trtn.temp=(d.charCodeAt(0)<<6 | d.charCodeAt(1)>>2)*0.25;
      trtn.fault=0;
      if (d.charCodeAt(1) & 1)  {
        var fault = (d.charCodeAt(3) & 7);
        trtn.fault=fault;
        switch (fault) {
          case 1:
            trtn.faultstring="No probe detected";
            break;
          case 3:
            trtn.faultstring="Probe shorted to Ground";
            break;
          case 4:
            trtn.faultstring="Probe shorted to VCC";
            break;
        }
      } 
      return trtn;
    };
    

    Should now return an object with properties temp (the temperature), fault (the fault code) and faultstring (with a description of the error condition, if available).

    Version on my website updated, so this should work:

    
    SPI1.setup({ miso:B4, sck:B3, baud:1000000 });
    var max=require("http://drazzy.com/espruino/MAX31855.js").connect(SPI1,C0);
    console.log(max.getTemp());
    
    

    I'll be submitting this module if it works - want me to credit you as something more, ah, personal than "User7341"? :-P

  • Just a little enhancement to reduce the code size: i guess its unnecessary to define the var fault. You stored the information in the object (see line 17.) why not use the object as default?

    trtn.fault = (d.charCodeAt(3) & 7);
        switch (trtn.fault) { ... }
    

    and you can combine these lines:

    var trtn={};
    trtn.temp=(d.charCodeAt(0)<<6 | d.charCodeAt(1)>>2)*0.25;
    trtn.fault=0;
    -------------------------
    var trtn={
        temp: (d.charCodeAt(0)<<6 | d.charCodeAt(1)>>2)*0.25
        fault: 0
    };
    

    Sorry, to be a little bit niggling :-) Memory is a limited resource! (it's hard to say this in a time of 2014)

  • Thanks, updated per your suggestion.

    If this works (I can't test - I don't have one of the chips on hand), I'll make a pull request this weekend.

  • I will test tomorrow but still think a couple of changes need to be made.

    var d = SPI1.send("\0\0\0\0",C0);  
    
    //needs to be changed to 
    
    var d = this.spi.send("\0\0\0\0",this.cs);
    
    

    This will allow more than one temp sensor to be connected and report temperature.

    The else statement needs to be added back in at the end. See my code above. The reason for this is you only want the temperature reported if everything is ok. If a fault code is displayed then you only want that code. If not you get the fault code as well as a incorrect temperature reading. Once this is done I will test again and let you know if it works.

    Really glad that I shared this code as I learnt a lot about OOP javascript today from everyones responses. Even though I have been reading a really good book on the subject, this thread really helped to cement all the pieces in place.

    So thank you to all who responded.

  • Post a reply
    • Bold
    • Italics
    • Link
    • Image
    • List
    • Quote
    • code
    • Preview
About

SPI question

Posted by Avatar for user7143 @user7143

Actions