B4R Question SPI Library

atiaust

Active Member
Licensed User
Longtime User
Hi All,

Does anyone know if the SPI library for B4R was ever added?

I am trying to read data from a MCP3551 22bit A2D converter which has a SPI interface.

Anyone had any experience with this device?

Thanks
 

atiaust

Active Member
Licensed User
Longtime User
Thanks Erel,

I did look at the code module but I do not know how to use it.

I have the SPI connected to a WEMOS D1 mini using D5 as SCK, D8 as SS and D6 as MISO.

Is there some code or tutorial showing how to assign the pins and access the code module?

Any help gratefully appreciated.

Thanks
 
Upvote 0

Roycefer

Well-Known Member
Licensed User
Longtime User
There are two methods in that code module that show how to use the code module with a DAC and an ADC.
 
Upvote 0

atiaust

Active Member
Licensed User
Longtime User
Thanks Roycefer,

I should have been a little clearer with my question.

I can see the two methods but not clear on the IO for the SPI device.

Can you tell me if the pin assignments in the code below are correct or am I missing something.

B4X:
Sub Process_Globals
    'These global variables will be declared once when the application starts.
    'Public variables can be accessed from all modules.
    Public Serial1 As Serial
    Private D1 As D1Pins
    Private SCK As Pin
    Private SS As Pin
    Private MISO As Pin
'   
End Sub

Private Sub AppStart
    Serial1.Initialize(115200)
    Log("AppStart")
'   
    SCK.Initialize(D1.D5, SCK.MODE_OUTPUT)
    SS.Initialize(D1.D8, SS.MODE_OUTPUT)
    MISO.Initialize(D1.D6, MISO.MODE_INPUT)
    AddLooper("Looper1")
End Sub

Sub looper1
    SPI.adcSingleChannelRead(SS,??)
End Sub

Thanks
 
Upvote 0

atiaust

Active Member
Licensed User
Longtime User
Hi Roycefer,

The pins in the code above are the SPI pins for the WEMOS D1 mini.

I am unsure of how to actually read the SPI device using your module.

Is it something like:
Dim Result as Double = SPI.adcSingleChannelRead(SS, readAddress) What is the readAddress?
 
Last edited:
Upvote 0

Roycefer

Well-Known Member
Licensed User
Longtime User
The SPI.adcSingleChannelRead method is for an MCP3008 which is an 8-channel ADC. That means you need to pass the channel's address to the ADC and the ADC will pass the analog value it read on that channel back to you.

You are using an MCP3551 which only has one channel. I don't think the SPI.acSingleChannelRead method will work for this device. You will need to read the MCP3551's datasheet to see what it expects. If you can find some Arduino code that interfaces with the MCP3551 we can probably convert that to work with B4R and the SPI code module.
 
Upvote 0

atiaust

Active Member
Licensed User
Longtime User
Here is some Arduino code. I will try to get this to work using Arduino.

B4X:
/*
pins:
 cs=8
 sdo/rdy=12
 sck=13
*/

#include <SPI.h>

unsigned char sspin=8; //cs pin

union{
        int32_t value;
        uint8_t aa[4];
    } c ;
    

void setup(void){
pinMode(12,INPUT);  //to check ready pin
pinMode(sspin,OUTPUT);
digitalWrite(sspin,HIGH);//for single conversion
SPI.begin();
SPI.setBitOrder(MSBFIRST);
SPI.setDataMode(SPI_MODE3);
SPI.setClockDivider(SPI_CLOCK_DIV16);//max. speed of chip is 5 Mhz
Serial.begin(9600); 

}

void loop(void){
 
digitalWrite(sspin,LOW);

while(digitalRead(12)){
 
  digitalWrite(sspin,LOW);
                    
                    }
c.aa[2]=SPI.transfer(0x00);
c.aa[1]=SPI.transfer(0x00);
c.aa[0]=SPI.transfer(0x00);
c.aa[3]=0x00;
digitalWrite(sspin,HIGH);
//check if overflow has occured
if((c.aa[2]&(1<<6))|(c.aa[2]&(1<<7))){
  c.aa[2]&=~(1<<6);
  Serial.println(c.value);
}
//check if sign bit is affected. if so, since it is two's compliment,
// substract it from 2^N
else if(c.aa[2]&(1<<5)){
c.value=0x400000-c.value;
Serial.println(c.value);
}

else{
Serial.println(c.value);
}
  delay(10);

}

I have the spec sheet for the MCP3551 but it is too big to upload.

Thanks for your assistance.
 
Upvote 0

Roycefer

Well-Known Member
Licensed User
Longtime User
Add these two subs to the SPI code module:
B4X:
Public Sub MCP3551Read(clckSpeed As Int, chipSelectPin As Pin) As Long
    chipSelectPin.DigitalWrite(True)
    BeginTransaction(clckSpeed,MSBFIRST,SPI_MODE(3))
    chipSelectPin.DigitalWrite(False)
    Dim b(4) As Byte
    b(2) = Transfer(0x00)
    b(1) = Transfer(0x00)
    b(0) = Transfer(0x00)
    b(3) = 0x00
    chipSelectPin.DigitalWrite(True)
    Dim res As Long = 0
    EndTransaction
    Dim r As RandomAccessFile
    If UintToBoolean( Bit.Or( Bit.And(b(2),Bit.ShiftLeft(1,6)), Bit.And(b(2),Bit.ShiftLeft(1,7)) )) Then
        b(2) = Bit.And(b(2),Bit.Not(Bit.ShiftLeft(1,6)))
        Dim r As RandomAccessFile
        r.Initialize(b,True)
        res = r.ReadLong32(0)
    Else if UintToBoolean(Bit.And(b(2),Bit.ShiftLeft(1,5))) Then
        r.Initialize(b,True)
        res = r.ReadLong32(0)
        res = 0x400000-res
    End If
    Return res
End Sub

Public Sub UintToBoolean(u As UInt) As Boolean
    Return u<>0
End Sub

Note that this isn't tested. You will have to test and debug it yourself. This is just a literal translation of the Arduino code you posted. But it should get you started on the right path.
 
Upvote 0

atiaust

Active Member
Licensed User
Longtime User
Thanks Roycefer,

I have added it in to the app as suggested.

I need to get the device that provides the analog signal to the MCP3551 working correctly before I can test it.

Thanks for your assistance. I will let you know the outcome.
 
Upvote 0
Top