Pages: 1 2 [3]   Go Down
Author Topic: How to set SPI clock to 76.9kHz by using the UNO R3?  (Read 4002 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 28
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
How to make MOSI idle high?

MOSI is idling high in your screenshot.

No. In "Post to Fourm_Arduino SPI Library.jpg", MOSI is blue. MOSI is idling on the state of last bit of last transmission.

I will reply to the other comments tomorrow.

Thanks.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 28
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

my code-1
Code:
#include "Arduino.h"
//include the SPI library
#include <SPI.h>

const int CMD_IDLE_TIME_3 = 200 ;
const int CMD_IDLE_TIME_4 = 300 ;

const int CLKpin = 13; // set pin 13 as the CLK
const int MOSIpin = 11; // set pin 11 as the MOSI
const int MISOpin = 12; // set pin 12 as the MISO
const int SSpin = 10; // set pin 10 as the SS; NOT conntect into circuit; slave hasn't SS;

byte My_SPI_Transfer(byte MOSI_data){
  /* Set CLK to output clock pulse */
  pinMode(CLKpin,OUTPUT);
  byte MISO_data=SPI.transfer(MOSI_data);
  /* Set CLK to input so that Slave can issue busy signal on CLK, which pull down the clock */
  pinMode(CLKpin,INPUT);
  digitalWrite(CLKpin,0);
  return MISO_data; // return MISO_data to My_SPI_Transfer function
}

// initialize setup
void setup(){
  // prescales the whole system clock from 16MHz down to 8MHz
  CLKPR = 0b10000000;
  CLKPR = 0b00000001;
  
  Serial.begin(9600); // if sys clock is 8MHz, choose half baud rate in serial monitor
  
  pinMode (CLKpin, OUTPUT); // set CLKpin as an output
  pinMode (MOSIpin, OUTPUT); // set MOSIpin as an output
  pinMode (MISOpin, INPUT); // set MISOpin as an input
  pinMode (SSpin, OUTPUT); // set SSpin as an output
  digitalWrite(MISOpin,1); // Enable pull-up resister
  
  SPI.begin(); // initialize SPI
  SPI.setBitOrder(MSBFIRST); // set the order of the bits
  SPI.setDataMode(SPI_MODE3); // set clock polarity and clockphase
  SPI.setClockDivider(SPI_CLOCK_DIV128); // set CLK rate: 62.5kHz
  
  
}



void loop() {
  
  My_SPI_Transfer(0x00);
  delayMicroseconds(CMD_IDLE_TIME_3);
  
  byte resp = My_SPI_Transfer(0x0A);
  Serial.println(resp,HEX);
  delayMicroseconds(CMD_IDLE_TIME_3);
  
}

How to make MOSI idle high?
Now MOSI idle is random. If last transfer is (0x01)=(00000001)bin, the MOSI idle keeps the last bit 1 , which is high; if last transfer is (0x0A)=(00001010), the MOSI keeps the last bit 0, which is low.

Why the MISO rises slowly and has noise that seems coupling with the rising of clock? I want to improve that.

Thanks.

Blue Line: MOSI;
Yellow Line: CLK;
Green Line: MISO;

1st attachment is the screenshot of running my code-1 based on Arduino SPI library.



2nd attachment is the screenshot of running my code-2 based on USART in SPI mode.
My code-2 uses 0-RX and 1-TX. I have to reserve 0-RX and 1-TX for serial monitor; so I cannot use code-2. The waveform is much better than code-1. This waveform is what I want to achieve.


my code-2

Code:
#include "Arduino.h"


const int CMD_IDLE_TIME_3 = 200 ;
const int CMD_IDLE_TIME_4 = 300 ;


/* Circuit Pin Defination */
const int CLKpin = 4; // set pin 4 as the CLK
const int MOSIpin = 1; // set pin 1 as the MOSI
const int MISOpin = 0; // set pin 0 as the MISO
const int SSpin = 2; // set pin 2 as the SS

/* Fake SPI Initialise Function Based on UART. NOT the SPI Library in the Arduino System */
// Thank TCWORLD for help

void SPI_Initialise() {
  pinMode(MOSIpin,OUTPUT); // MOSI
  pinMode(CLKpin,OUTPUT); // CLK pin
  pinMode(SSpin,OUTPUT); // SS pin
  pinMode(MISOpin,INPUT); // MISO
  
  /* Set USART as SPI */
  /* ATmega 328 Data Sheet: http://www.atmel.com/Images/doc8271.pdf */
  UBRR0 = 0; // UBRRn: Baud Rate Registers
  PRR = (0<<PRSPI); // PRR: Power Reduction Register; PRSPI: Power Reduction Serial Peripheral Interface
  /* Set to MasterSPI (UMSEL01=1, UMSEL00=1), in Mode3 (UCPHA0=1, UCPOL0=1) */
  UCSR0C = (1<<UMSEL01)|(1<<UMSEL00)|(1<<UCPHA0)|(1<<UCPOL0);  // UMSELn1 & UMSELn0: USART Mode Select
  UCSR0B = (1<<RXEN0)|(1<<TXEN0); //Enable TX and RX (TX = MOSI, RX = MISO)
  
/* clock rate: UBRR0 = (FCPU/(2*BAUD)) -1;
  for 62.5kHz or 16us pulse, UBRR0 = (16000000/(2*62500))-1 = 127;
  for 76.9kHz or 13us pulse, UBRR0 = (16000000/(2*76900))-1 = 103;
  for 57.6kHz or 17us pulse, UBRR0 = (16000000/(2*57600))-1 = 138; */
  UBRR0 = 127; // UBRRn: Baud Rate Registers
}

/* Fake SPI Protocol Function Based on UART. NOT the SPI Library in the Arduino System */
byte SPI_Transfer(byte data) {
  /* Wait for empty transmit buffer */
  while ( !( UCSR0A & (1<<UDRE0)) ); // UDREn: USART Data Register Empty; UCSRnA: USART Control and Status Register
  /* Put data into buffer, sends the data */
  UDR0 = data; // UDRn: USART I/O Data Register
  
  /* Wait for data to be received */
  while ( !(UCSR0A & (1<<RXC0)) ); // RXCn: USART Receive Complete
  /* Get and return received data from buffer */
  return UDR0; // UDRn: USART I/O Data Register
}

byte My_SPI_Transfer(byte MOSI_data){
  /* Set CLK to output clock pulse */
  pinMode(CLKpin,OUTPUT);
  /* Call SPI_Transfer mentioned above */
  byte MISO_data=SPI_Transfer(MOSI_data); //
  /* Set CLK to input so that slave can issue busy signal on CLK, which pull down the clock */
  pinMode(CLKpin,INPUT);
  digitalWrite(CLKpin,0);
  return MISO_data;
}

/* Initialise the Entire Code */
void setup(){
  SPI_Initialise();
}

/* Main Body of the Entire Code */
void loop(){

  
  My_SPI_Transfer(0x00);
  delayMicroseconds(CMD_IDLE_TIME_3);
  
  My_SPI_Transfer(0x0A);
  delayMicroseconds(CMD_IDLE_TIME_3);
  
}









 
Logged

Global Moderator
Offline Offline
Brattain Member
*****
Karma: 485
Posts: 18806
Lua rocks!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

OK. Well a bit of testing shows it idles high in modes 0 and 2, and idles low in modes 1 and 3.
Logged


Global Moderator
Offline Offline
Brattain Member
*****
Karma: 485
Posts: 18806
Lua rocks!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

That's the third time you started a new thread about this exact topic. Start another and look forwards to a bit of time out.

Threads merged, again. (New thread is now reply #31 above).

- Moderator
Logged


Offline Offline
Newbie
*
Karma: 0
Posts: 28
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

That's the third time you started a new thread about this exact topic. Start another and look forwards to a bit of time out.

Threads merged, again. (New thread is now reply #31 above).

- Moderator

ok. I posted a new topic, but finally I found the new topic is in the old thread. I guessed that I posted it in my old thread by mistake. Then, I post it again as a new topic(you said third time). I didn't realize that you merged the second post.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 28
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
I tried your code. It gives me a ramp CLK and MOSI when I put BB_SPITransfer(0x0A) in the void loop()

That's not the code's fault. Have you got capacitors on those lines? What capture mode is the oscilloscope on? AC or DC?

the oscilloscope is Agilent MSO-9104A. the channel setup is on DC coupling, which is the default setup.

I haven't add external capacitor on these lines. I am controlling a lens that may has a IC,CPU, operation amplifier, BJT, several capacitor(less than 10) and some resistors in side.

PS: I try AC coupling mode on oscilloscope, the waveform is same as the old waveform.
« Last Edit: July 09, 2012, 11:01:24 am by jenaflex » Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 28
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

my code-1

I can't reproduce your problem. Using my code-1 above, I get:



Do you have anything like resistors or capacitors on those lines?

That's because you haven't connect lens. You are showing the MOSI and CLK, which are fine on my oscillocope. The MISO is the one that has issue.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 28
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

OK. Well a bit of testing shows it idles high in modes 0 and 2, and idles low in modes 1 and 3.
Blue: MOSI; Yellow: CLK ; Green: MISO

I use "my code-1" to send 0x0A (00001010) and 0x0F (00001111) without lens connection.

The green wave is MISO. Without connecting lens, MISO still has the attenuation that is coupling with the clock. Thus, I think there should be a repeatable issue. You can "run my code-1" and observe MISO.

The ramp decrease of CLK results from not connecting the lens. In "my code-1" and "my code-2", I turn on the pull-up resistor on the CLK after the clock cycle in order to let the lens issues a busy signal. Having connected a lens, the ramp decrease should be a step decrease. You can refer to the old screenshot for "my code-1".

0x0A, which ends with 0


0x0F, which ends with 1


This is the overall signals. 0x0A, then 0x0F, and then 0x0A
In the screenshot, the actually idle time between two signal transmission is much much longer than my setting in "delayMicrosecond(200)", I realize that the "serial.println()" slow down the time between two signal.


As I said before, the idle of MOSI is changing with the last bit of the transmission.

A little summary:
As long as using the Arduino SPi Library, even if I disconnect the slave device, the attenuation noise(like a wave of capasitor) coupling with the clock does exist. I try a simple version of "my code-1" and end up with the same result(noise is still there). So my code seems to be fine.

The first lens I test is new, but it was designed in 1990. All my screenshot are based on the first lens. The electronics might be "weak". Thus, it might not be "strong" enough to improve the signal of MISO. I test another lens that was released on 2007. Its signal is much better than the first lens I test.

I still want to figure out this issue because using USART in SPI mode will not have this issue for both of my lenses.

simple version of my code-1
Code:
#include "Arduino.h"
//include the SPI library
#include <SPI.h>

const int CLKpin = 13; // set pin 13 as the CLK
const int MOSIpin = 11; // set pin 11 as the MOSI
const int MISOpin = 12; // set pin 12 as the MISO
const int SSpin = 10; // set pin 10 as the SS


// initialize setup
void setup(){
  pinMode (CLKpin, OUTPUT); // set CLKpin as an output
  pinMode (MOSIpin, OUTPUT); // set MOSIpin as an output
  pinMode (MISOpin, INPUT); // set MISOpin as an input
  pinMode (SSpin, OUTPUT); // set SSpin as an output
  digitalWrite(MISOpin,1); // Enable pull-up resister
  
  SPI.begin(); // initialize SPI
  SPI.setBitOrder(MSBFIRST); // set the order of the bits
  SPI.setDataMode(SPI_MODE3); // set clock polarity and clockphase
  SPI.setClockDivider(SPI_CLOCK_DIV128); //
}



void loop() {
 
  SPI.transfer(0x00);
  delayMicroseconds(190);
  
  SPI.transfer(0x0A);
  delayMicroseconds(190);
  
}
____________


* 7-9-Signal_Arduino SPI Library_2.jpg (119.51 KB, 1024x768 - viewed 114 times.)

* 7-9-Signal_Arduino SPI Library_3.jpg (118.75 KB, 1024x768 - viewed 64 times.)

* 7-9-Signal_Arduino SPI Library_4.jpg (118.34 KB, 1024x768 - viewed 65 times.)
« Last Edit: July 09, 2012, 12:29:39 pm by jenaflex » Logged

Leeds, UK
Offline Offline
Edison Member
*
Karma: 80
Posts: 1726
Once the magic blue smoke is released, it won't go back in!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Just out of curiosity, what do you need the serial port for? If it is just uploading code, you could have a simple switch that breaks the MISO line when downloading. Then when done, you just need to reconnect the MOSI line.

If you need it for something such as talking to the pc when in use, you could try connecting the serial port pins from the USB-Serial IC to two other arduino pins and then use the SoftwareSerial library for serial communications and the hardware UART in SPI mode.
I have added a diagram of how you could do it. The Arduino has two resistors between the USB-UART IC, and the Atmega chip.
 If you add two wires between two other digital pins and the USB side of those resistors (as shown in green), then when you want to program it you disconnect the lens (possibly with as switch as shown), and it will program through the hardware port. When the program is running, you use the SoftwareSerial library to talk to the computer (in the diagram through D2 and D3).

As for why it doesn't work in the other method, the USB-Serial chip is acting like a strong 1k pullup resistor on the MISO line when it is not transmitting to the arduino. You could try it with the SPI and add a 1k pullup resistor to that and see if it helps. It is entirely possible that the lens doesn't have a strong enough driver.


* idea.png (12.51 KB, 507x319 - viewed 22 times.)
Logged

~Tom~

Global Moderator
Offline Offline
Brattain Member
*****
Karma: 485
Posts: 18806
Lua rocks!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

That's because you haven't connect lens. You are showing the MOSI and CLK, which are fine on my oscillocope. The MISO is the one that has issue.

I'm sorry, I must be missing something.

Quote
As long as using the Arduino SPi Library, even if I disconnect the slave device, the attenuation noise(like a wave of capasitor) coupling with the clock does exist.

With no slave device connected the MISO line would be floating would it not? There is no point in measuring what is on it.
Logged


Offline Offline
Newbie
*
Karma: 0
Posts: 28
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

That's because you haven't connect lens. You are showing the MOSI and CLK, which are fine on my oscillocope. The MISO is the one that has issue.

I'm sorry, I must be missing something.

Quote
As long as using the Arduino SPi Library, even if I disconnect the slave device, the attenuation noise(like a wave of capasitor) coupling with the clock does exist.

With no slave device connected the MISO line would be floating would it not? There is no point in measuring what is on it.

Without slave device,MISO stays high until clock occurs. The waveform is exactly the same as this screenshot.

_____________


The MISO should stay high because I turn on the internal pull-up resistor. But, it has noise coupling with CLK. The result is similar  with the one that connect lens. Recall the former screenshot(with lens connected)

_____________
« Last Edit: July 10, 2012, 10:23:02 am by jenaflex » Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 28
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Just out of curiosity, what do you need the serial port for? If it is just uploading code, you could have a simple switch that breaks the MISO line when downloading. Then when done, you just need to reconnect the MOSI line.

If you need it for something such as talking to the pc when in use, you could try connecting the serial port pins from the USB-Serial IC to two other arduino pins and then use the SoftwareSerial library for serial communications and the hardware UART in SPI mode.
I have added a diagram of how you could do it. The Arduino has two resistors between the USB-UART IC, and the Atmega chip.
 If you add two wires between two other digital pins and the USB side of those resistors (as shown in green), then when you want to program it you disconnect the lens (possibly with as switch as shown), and it will program through the hardware port. When the program is running, you use the SoftwareSerial library to talk to the computer (in the diagram through D2 and D3).

As for why it doesn't work in the other method, the USB-Serial chip is acting like a strong 1k pullup resistor on the MISO line when it is not transmitting to the arduino. You could try it with the SPI and add a 1k pullup resistor to that and see if it helps. It is entirely possible that the lens doesn't have a strong enough driver.

Thanks.

Do you mean that I can add external pullup resisitor and run "my code-1" based on SPI library  to eliminate the MISO noise as shown in this screenshot below? In "my code-1", I do turn on the internal pullup resister in the chip. But I end up with the MISO noise coupling with clock.


Quote
"As for why it doesn't work in the other method"

Do you mean the USART in SPI mode is better than the Arduino SPI library or AVR chip SPI? I wrote a code based on setting up resistors for AVR SPI, but the result is same as the Arduino SPI library.
Logged

Leeds, UK
Offline Offline
Edison Member
*
Karma: 80
Posts: 1726
Once the magic blue smoke is released, it won't go back in!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

The hardware SPI, and USART SPI have different hardware, and will behave differently. What I am not sure about is why it would work for one and not the other, which leads me to believe that it is not the atmega chip which is behaving weirdly, but rather the arduino UNO board is having an effect.

There are two differences in the board which could affect SPI performance.
The first is that rather annoyingly, the onboard LED is connected to the SPI clock pin. Its concievable that the power dropped through that LED could have a difference, especially if the Lens is an old TTL type interface which requires much more current from the pin than CMOS logic. This could explain the coupling between the two pins if you are drawing too much current from the clock pin - though this is unlikely.

The second difference is that the UART pins have the usb-serial chip driving them high through what is essentially a 1k resistor. This will theoretically mask the loading effect because a 1k pullup is fairly strong - and alot stronger than the internal 10k pullup.


What I suggest as you gathered is to use the Hardware SPI, and add a 1k pullup to the MISO pin and see if it helps.
Logged

~Tom~

Offline Offline
Newbie
*
Karma: 0
Posts: 28
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

The hardware SPI, and USART SPI have different hardware, and will behave differently. What I am not sure about is why it would work for one and not the other, which leads me to believe that it is not the atmega chip which is behaving weirdly, but rather the arduino UNO board is having an effect.

There are two differences in the board which could affect SPI performance.
The first is that rather annoyingly, the onboard LED is connected to the SPI clock pin. Its concievable that the power dropped through that LED could have a difference, especially if the Lens is an old TTL type interface which requires much more current from the pin than CMOS logic. This could explain the coupling between the two pins if you are drawing too much current from the clock pin - though this is unlikely.

The second difference is that the UART pins have the usb-serial chip driving them high through what is essentially a 1k resistor. This will theoretically mask the loading effect because a 1k pullup is fairly strong - and alot stronger than the internal 10k pullup.


What I suggest as you gathered is to use the Hardware SPI, and add a 1k pullup to the MISO pin and see if it helps.

Thanks. I read a nice article about pull-up resistor, and also read your comments carefully. Now, I believe I got some basic ideas that could explain the problem I met. I agree with your opinion. Most load connecting on the input pins performs like a capacitor, which will couple with the internal pull-up resistor as a RC filter. The transient time Tau = R * C. The lager the pull-up resistor is, the longer the rise time would be.

BTW, how can I disable the internal pull-up and add a external pull-up?

Thanks a lot. I did learn a lot.
Logged

Leeds, UK
Offline Offline
Edison Member
*
Karma: 80
Posts: 1726
Once the magic blue smoke is released, it won't go back in!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

You don't need to. Just add an external one along side. If the internal one is 10K, and you add a 1k externally, you would have a (10*1)/(10+1) = 0.909k pullup, which would be fine. If you used a 1.1k external pullup, you would have a 11/11.1 ~= 1k pullup.
Logged

~Tom~

Pages: 1 2 [3]   Go Up
Jump to: