Hola me gustaria saber si es posible editar la libreria SPI para dividir la frecuencia a 256, ya que por defecto solo deja hacerlo hasta 128, he intentado editar la libreria sin exito.
alguno os preguntareis para que quiero un SPI tan lento, es por que el dispositivo con el que deseo comunicar funciona con una frecuencia de reloj de 62.5khz, y mi placa funciona a 16mhz 16000/128=125khz ![]()
Evaluaste que sea posible? Leiste la hoja de datos, no lo recuerdo ahora pero es raro que una librería no respete todo el rango posible de un hardware disponible.
¿Has intentado así?
SPI.beginTransaction(SPISettings(62500, MSBFIRST, SPI_MODE0))
Efectivamente, el divisor de reloj spi no va más allá de 1/128, salvo en el arduino due.
Supongo que la librería tirará de software para frecuencias inferiores.

A traves de la configuración no parece ser posible, a menos que cambies la velocidad del reloj.
surbyte:
Evaluaste que sea posible? Leiste la hoja de datos, no lo recuerdo ahora pero es raro que una librería no respete todo el rango posible de un hardware disponible.
la verdad es que no he leido el datasheet pero la placa es arduino mega 2560 R3
noter:
¿Has intentado así?
SPI.beginTransaction(SPISettings(62500, MSBFIRST, SPI_MODE0))Efectivamente, el divisor de reloj spi no va más allá de 1/128, salvo en el arduino due.
Supongo que la librería tirará de software para frecuencias inferiores.
eso es de las primeras cosas que intente, al ponerle cualquier valor que ingrese inferior a 125000 lo ignora y fija el reloj a esa velocidad osea 16/128.
surbyte:
A traves de la configuración no parece ser posible, a menos que cambies la velocidad del reloj.
interesante tabla, nunca la habia visto, estudiando los parametros de configuracion queda claro que no puede dividirse mas alla de 128 veces.... ![]()
gracias por las respuestas, ahora intentare averiguar como conseguir esta velocidad, he leido sobre reducir la velocidad de reloj de la placa y no lo veo claro no soy mas que un principiante con arduino y no quisiera romperlo tan pronto jejeje,
por otra parte descargue un codigo sobre el que he trabajado un poco, este emula un bus SPI usando directamente las salidas 2, 3, y 4 de la placa pero sigo teniendo el mismo problema, demasiado rapido aunque mucho mas cerca que usando el SPI "nativo" de la placa
Vi que Nick Gammon hizo algo parecido un pseudo SPI. Busca en Google : Arduino SPI Nick Gammon
Lo que también puede tal vez servirte es modificar la frecuencia del cristal con lo que ello significa.
Vi que la bajan hasta 4Mhz. Busca por ahi.
¿La comunicación es en ambos sentidos o sólo en uno?
¿Puedes poner más detalles del dispositivo que quieres manejar?
surbyte:
Vi que Nick Gammon hizo algo parecido un pseudo SPI. Busca en Google : Arduino SPI Nick GammonLo que también puede tal vez servirte es modificar la frecuencia del cristal con lo que ello significa.
Vi que la bajan hasta 4Mhz. Busca por ahi.
interesante, voy a buscarlo respecto a lo de cambiar la frecuencia del cristal es lo que comente mas arriba, no me apetece cargarme la placa tan pronto, no tengo tantos conocimientos como para meterme en ello, ayer estuve buscando y vi que se puede llegar a bajar hasta 1Mhz.
estoy trabajamdo sobre este codigo,
si visitas esta pagina
te haras a la idea de lo que trato de hacer, basicamente es lo mismo pero con ligeras diferencias, lo que este hombre ha hecho le ha funcionado bien en su "cuadro de instrumentos" marca audi, yo poseo otro igual pero es marca volkswagen, he conseguido corregir las diferencias para hacerlo funcionar como deberia pero hay un par de puntos que no consigo corregir;
simplificando mucho este es el mensaje que envia mi radio a el cuadro de instrumentos para mostrar texto en pantalla, la frecuencia es 62.5 khz.
y este es el que he conseguido enviar con arduino, la frecuencia es 41.67 khz.
aun estoy estudiando manuales de programacion para poder comprender bien el codigo y hacer los ajustes necesarios, hasta el momento he conseguido un mensaje casi "calcado" al original de la radio salvo que la señal ENABLE pasa a nivel bajo despues de cada Byte enviado y por supuesto la frecuencia de reloj, la cual creo que es la responsable que aun no funcione correctamente
para mas informacion decir que dispongo de un analizador logico, la radio original y el cuadro de instrumentos para hacer las pruebas en cada modificacion que realizo, hasta ahora solo he conseguido que el cuadro mantenga el texto previamente enviado por la radio a pesar de que esta este apagada, podria ser por que al apagarse mande un mensaje para borrarla... aun es muy pronto para conclusiones definitivas
noter:
¿La comunicación es en ambos sentidos o sólo en uno?
¿Puedes poner más detalles del dispositivo que quieres manejar?
hola noter no, en principio solo tengo que enviar datos ya que es un display pero mas adelante me gustaria que arduino tambien reciba datos desde la radio pero esto lo veo aun muy lejano
Mira, esta es la pagina de Nick Gammon a la que me refería. Como siempre el analiza todo el tema, de 0 al máximo. Incluso una posible solución si no la malentiendo que puede ayudarte.
SPI - Serial Peripheral Interface - for Arduino
Creo que la vía que indica surbyte es la más apropiada. La librería bitBangedSPI con el parámetro constructor delayUs adecuado debería funcionar correctamente.
Habrá que calcular qué valor delayUs es el apropiado, teniendo en cuenta que ese valor indica los milisegundos que permanece la señal de reloj en cada bit.
gracias por las respuestas, ayer estuve estudiando un poco el tema pero aun no he conseguido la velocidad deseada
#include <Arduino.h>
class bitBangedSPI
{
// pins
const int mosi_;
const int miso_;
const int sck_;
// delay for clock being high
unsigned long delayUs_;
public:
// constructor
bitBangedSPI (const int mosi, const int miso, const int sck, const unsigned long delayUs = 8)
: mosi_ (mosi), miso_ (miso), sck_ (sck), delayUs_ (delayUs) { }
void begin ();
byte transfer (byte input);
enum { NO_PIN = -1 };
}; // end of bitBangedSPI
he cambiado el delayUs a 8, antes era 4 y no ha cambiado la velocidad, alguna idea?
Tu quieres bajar la velocidad no subir. Poner delay 4 sube.
Deberías probar con delayUs en 16 por ejemplo.
Sino ya sabes.
Consulta en inglés al Nick Gammon si te responde. Pero no le envíes personalmente o bien registrate en su foro y ahi si te responderá personalmente.
Podrías poner el código con el que estás intentando comunicar para darte alguna directriz más concreta. Por si acaso, te digo que no es necesario que modifiques la librería en sí; tan sólo incluirla, y crear el puerto, incluyendo además de los pines MOSO, MISO, SCK, el delayUs:
bitBangedSPI bbSPI (5, 6, 7, 16);
Yo comenzaría con 16, o incluso algo más generoso (64 o 128), pues es más fácil que falle la comunicación por excesiva velocidad que por demasiada lentitud. Podrías hacer incluso un programilla en el que le introduzcas por serie el delayUs a probar.
este es
//data pin 4
//clk pin 3
//ena pin 2
//WRITE TO CLUSTER
#define FIS_WRITE_ENA 2
#define FIS_WRITE_CLK 3
#define FIS_WRITE_DATA 4
#define FIS_WRITE_PULSEW 50
#define FIS_WRITE_STARTPULSEW 100
#define FIS_WRITE_START 15 //something like address, first byte is always 15
//END WRITE TO CLUSTER
//#define BINCODE 000011111011111010101010101110111011011010111100101100111010101010111101101011001011001110110000101010011011111010110100101101101011111010010011
// 000011111011111010101010101110111011011010111100101100111010101010111101101011001011001110110000101010011011111010110100101101101011111010010011
//int BINCODE[144]={
//0,0,0,0,1,1,1,1,
//1,0,1,1,1,1,1,0,
//1,0,1,0,1,0,1,0,
//1,0,1,1,1,0,1,1,
//1,0,1,1,0,1,1,0,
//1,0,1,1,1,1,0,0,
//1,0,1,1,0,0,1,1,
//1,0,1,0,1,0,1,0,
//1,0,1,1,1,1,0,1,
//1,0,1,0,1,1,0,0,
//1,0,1,1,0,0,1,1,
//1,0,1,1,0,0,0,0,
//1,0,1,0,1,0,0,1,
//1,0,1,1,1,1,1,0,
//1,0,1,1,0,1,0,0,
//1,0,1,1,0,1,1,0,
//1,0,1,1,1,1,1,0,
//1,0,0,1,0,0,1,1};
//WRITE TO CLUSTER
String FIS_WRITE_line1="";
String FIS_WRITE_line2="";
long FIS_WRITE_rotary_position_line1=-8;
long FIS_WRITE_rotary_position_line2=-8;
char FIS_WRITE_CHAR_FROM_SERIAL;
int FIS_WRITE_line=1;
long FIS_WRITE_last_refresh=0;
int FIS_WRITE_nl=0;
int FIS_WRITE_ENA_STATUS=0;
uint8_t FIS_WRITE_CRC=0;
//END WRITE TO CLUSTER
//WRITE TO CLUSTER
void FIS_WRITE_sendTEXT(String FIS_WRITE_line1,String FIS_WRITE_line2);
void FIS_WRITE_sendByte(int Bit);
void FIS_WRITE_startENA();
void FIS_WRITE_stopENA();
//END WRITE TO CLUSTER
void setup(){
//WRITE TO CLUSTER
pinMode(FIS_WRITE_ENA, OUTPUT);
digitalWrite(FIS_WRITE_ENA,LOW);
pinMode(FIS_WRITE_CLK, OUTPUT);
digitalWrite(FIS_WRITE_CLK, HIGH);
pinMode(FIS_WRITE_DATA, OUTPUT);
digitalWrite(FIS_WRITE_DATA, HIGH);
Serial.begin(9600);
//END WRITE TO CLUSTER
}
void loop(){
//WRITE TO CLUSTER
if (Serial.available()) {
FIS_WRITE_CHAR_FROM_SERIAL=(char)Serial.read();
Serial.print(FIS_WRITE_CHAR_FROM_SERIAL);
if (FIS_WRITE_CHAR_FROM_SERIAL == '\n') {
FIS_WRITE_nl=1;
if (FIS_WRITE_line==1){
FIS_WRITE_line=2;
} else {
FIS_WRITE_line=1;
}
} else {
if (FIS_WRITE_line==1){
if (FIS_WRITE_nl){
FIS_WRITE_nl=0;
FIS_WRITE_line1="";
FIS_WRITE_rotary_position_line1=-8;
}
FIS_WRITE_line1+=FIS_WRITE_CHAR_FROM_SERIAL;
} else {
if (FIS_WRITE_nl){
FIS_WRITE_nl=0;
FIS_WRITE_line2="";
FIS_WRITE_rotary_position_line2=-8;
}
FIS_WRITE_line2+=FIS_WRITE_CHAR_FROM_SERIAL;
}
}
}
int FIS_WRITE_line1_length=FIS_WRITE_line1.length();
int FIS_WRITE_line2_length=FIS_WRITE_line2.length();
String FIS_WRITE_sendline1=" ";
String FIS_WRITE_sendline2=" ";
//do rotary and refresh each 0.5second
//refresh cluster each 5s
if(millis()-FIS_WRITE_last_refresh>500 && (FIS_WRITE_line1_length>0 || FIS_WRITE_line2_length>0)){
if (FIS_WRITE_line1_length>8){
for (int i=0;i<8;i++){
if (FIS_WRITE_rotary_position_line1+i>=0 && (FIS_WRITE_rotary_position_line1+i)<FIS_WRITE_line1_length) {
FIS_WRITE_sendline1[i]=FIS_WRITE_line1[FIS_WRITE_rotary_position_line1+i];
}
}
if (FIS_WRITE_rotary_position_line1<FIS_WRITE_line1_length){
FIS_WRITE_rotary_position_line1++;
} else {
FIS_WRITE_rotary_position_line1=-8;
FIS_WRITE_sendline1=" ";
}
} else {
FIS_WRITE_sendline1=FIS_WRITE_line1;
}
if (FIS_WRITE_line2_length>8){
for (int i=0;i<8;i++){
if (FIS_WRITE_rotary_position_line2+i>=0 && (FIS_WRITE_rotary_position_line2+i)<FIS_WRITE_line2_length) {
FIS_WRITE_sendline2[i]=FIS_WRITE_line2[FIS_WRITE_rotary_position_line2+i];
}
}
if (FIS_WRITE_rotary_position_line2<FIS_WRITE_line2_length){
FIS_WRITE_rotary_position_line2++;
} else {
FIS_WRITE_rotary_position_line2=-8;
}
} else {
FIS_WRITE_sendline2=FIS_WRITE_line2;
}
// Serial.println("refresh");
FIS_WRITE_sendTEXT(FIS_WRITE_sendline1,FIS_WRITE_sendline2);
FIS_WRITE_last_refresh=millis();
//end refresh
}
//END WRITE TO CLUSTER
}
//WRITE TO CLUSTER
void FIS_WRITE_sendTEXT(String FIS_WRITE_line1,String FIS_WRITE_line2) {
Serial.println(FIS_WRITE_line1);
Serial.println(FIS_WRITE_line2);
int FIS_WRITE_line1_length=FIS_WRITE_line1.length();
int FIS_WRITE_line2_length=FIS_WRITE_line2.length();
if (FIS_WRITE_line1_length<=8){
for (int i=0;i<(8-FIS_WRITE_line1_length);i++){
FIS_WRITE_line1+=" ";
}
}
if (FIS_WRITE_line2_length<=8){
for (int i=0;i<(8-FIS_WRITE_line2_length);i++){
FIS_WRITE_line2+=" ";
}
}
FIS_WRITE_CRC=(0xFF^FIS_WRITE_START);
FIS_WRITE_startENA();
FIS_WRITE_sendByte(FIS_WRITE_START);
for (int i = 0; i <= 7; i++)
{
FIS_WRITE_sendByte(0xFF^FIS_WRITE_line1[i]);
FIS_WRITE_CRC+=FIS_WRITE_line1[i];
}
for (int i = 0; i <= 7; i++)
{
FIS_WRITE_sendByte(0xFF^FIS_WRITE_line2[i]);
FIS_WRITE_CRC+=FIS_WRITE_line2[i];
}
FIS_WRITE_sendByte(FIS_WRITE_CRC%0x100);
FIS_WRITE_stopENA();
}
void FIS_WRITE_sendByte(int Byte){
static int iResult[8];
for (int i = 0; i <= 7; i++)
{
iResult[i] = Byte % 2;
Byte = Byte / 2;
}
for(int i=7;i>=0;i--){
switch (iResult[i]) {
case 1: digitalWrite(FIS_WRITE_DATA,HIGH);
break;
case 0:digitalWrite(FIS_WRITE_DATA,LOW);
break;
}
digitalWrite(FIS_WRITE_CLK,LOW);
delayMicroseconds(FIS_WRITE_PULSEW);
digitalWrite(FIS_WRITE_CLK,HIGH);
delayMicroseconds(FIS_WRITE_PULSEW);
}
}
void FIS_WRITE_startENA(){
if (!digitalRead(FIS_WRITE_ENA)) {
digitalWrite(FIS_WRITE_ENA,HIGH);
// delayMicroseconds(FIS_WRITE_STARTPULSEW);
// digitalWrite(FIS_WRITE_ENA,LOW);
// delayMicroseconds(FIS_WRITE_STARTPULSEW);
// digitalWrite(FIS_WRITE_ENA,HIGH);
// delayMicroseconds(FIS_WRITE_STARTPULSEW);
// FIS_WRITE_ENA_STATUS=1;
}
}
void FIS_WRITE_stopENA(){
digitalWrite(FIS_WRITE_ENA,LOW);
// FIS_WRITE_ENA_STATUS=0;
}
//END WRITE TO CLUSTER
nadie me puede ayudar?? sigo dando palos de ciego...
ya he conseguido una velocidad comprensible para el display, ya muestro mensajes en el display. ahora el problema es calcular la suma de verificacion del mensaje enviado, si fuerzo esta al byte que manda la radio lo muestra sin problemas pero como puedo calcular dicha suma a partir de mensajes capturados de la radio???
La suma de verificación no será un CRC?
La suma de verificación no será un CRC?
Si no pones ejemplos forzados con los datos recibidos y el forzado, no se como podemos entenderte.
Supongamos que estoy en lo correcto. Esta sería una posible solución
Los datos deben pasarse con un puntero pero es posible modificarla para lo que quieras usar.
// KIRSP Global Variables for CRC-16 Checking
unsigned char KIRSP_CRC16_Hi_Byte = 0xFF; // Do not modify
unsigned char KIRSP_CRC16_Low_Byte = 0xFF; // Do not modify
unsigned int KIRSP_cal_CRC16(unsigned char *CRC16_Data_Array, unsigned short CRC16_Data_Array_Len)
{
unsigned int x = 0xFFFF;
unsigned int y;
int i;
x ^= *CRC16_Data_Array;
for (i = 0; i < 8; ++i) {
if (x & 1)
x = (x >> 1) ^ 0xA001; // <----The key
else
x = (x >> 1);
}
KIRSP_CRC16_Hi_Byte = highByte(x);
KIRSP_CRC16_Low_Byte = lowByte(x);
y = x;
CRC16_Data_Array_Len--;
*CRC16_Data_Array++;
while (CRC16_Data_Array_Len--)
{
y ^= *CRC16_Data_Array;
for (i = 0; i < 8; ++i)
{
if (y & 1)
y = (y >> 1) ^ 0xA001; // <---The Key
else
y = (y >> 1);
}
KIRSP_CRC16_Hi_Byte = highByte(y);
KIRSP_CRC16_Low_Byte = lowByte(y);
*CRC16_Data_Array++;
}
KIRSP_CRC16_Hi_Byte = lowByte(y); // write to global variable
KIRSP_CRC16_Low_Byte = highByte(y); // write to global variable
return y;
} // end of KIRSP_cal_CRC16 function
Acá te dejo el link CRC-16 Error checking
surbyte:
La suma de verificación no será un CRC?
Si no pones ejemplos forzados con los datos recibidos y el forzado, no se como podemos entenderte.
Supongamos que estoy en lo correcto. Esta sería una posible solución
Los datos deben pasarse con un puntero pero es posible modificarla para lo que quieras usar.// KIRSP Global Variables for CRC-16 Checking
unsigned char KIRSP_CRC16_Hi_Byte = 0xFF; // Do not modify
unsigned char KIRSP_CRC16_Low_Byte = 0xFF; // Do not modify
unsigned int KIRSP_cal_CRC16(unsigned char *CRC16_Data_Array, unsigned short CRC16_Data_Array_Len)
{
unsigned int x = 0xFFFF;
unsigned int y;
int i;
x ^= *CRC16_Data_Array;
for (i = 0; i < 8; ++i) {
if (x & 1)
x = (x >> 1) ^ 0xA001; // <----The key
else
x = (x >> 1);
}
KIRSP_CRC16_Hi_Byte = highByte(x);
KIRSP_CRC16_Low_Byte = lowByte(x);
y = x;
CRC16_Data_Array_Len--;
*CRC16_Data_Array++;
while (CRC16_Data_Array_Len--)
{
y ^= *CRC16_Data_Array;
for (i = 0; i < 8; ++i)
{
if (y & 1)
y = (y >> 1) ^ 0xA001; // <---The Key
else
y = (y >> 1);
}
KIRSP_CRC16_Hi_Byte = highByte(y);
KIRSP_CRC16_Low_Byte = lowByte(y);
*CRC16_Data_Array++;
}
KIRSP_CRC16_Hi_Byte = lowByte(y); // write to global variable
KIRSP_CRC16_Low_Byte = highByte(y); // write to global variable
return y;
} // end of KIRSP_cal_CRC16 function
Acá te dejo el link [CRC-16 Error checking](http://forum.arduino.cc/index.php?topic=45859.0)
gracias por la respuesta surbyte.
El mensaje enviado en esta captura es "IDM FM1 2" la suma de verificacion a este mensaje es F5
aqui tienes una captura, en ella los 3 primeros bytes son siempre iguales, da igual el mensaje que se envie siempre son asi, el ultimo byte es la suma de verificacion, no se si es una suma CRC16 la verdad es que no tengo ni idea que tipo de suma es.
he estado indagando y he conseguido mostrar en el diplay el mensaje "1000" la secuencia de bytes enviados es la siguiente.
"7E ED 0F CE CF CF CF DF DF DF DF DF DF DF DF DF DF DF DF 9E"
en ella hay que matizar que los bytes estan invertidos o negados para poder representar correctamente los datos, la secuencia CE CF CF CF corresponde a "1000", CE negado es 31= 1 en ASCII, CF negado es 30=0 en ASCII los bytes DF son espacios en blanco. he probado enviando numeros , obteniendo la siguiente correspondencia de suma de verificacion:
0000=9D 0001=9E 0002=9F 0003=A0 0004=99 0005=9A 0006=9B 0007=9C 0008=95 0009=96
0010=9E 0011=9D 0012=A0 0013=9F 0014=9A 0015=99 0016=9C
1000=9E 2000=9F 3000=A0 4000=99 5000=9A 6000=9B 7000= 9C 8000= 95 9000= 96
espero haberme explicado con claridad.
Llevo un rato viendo ciertas relaciones por ejemplo 1000=9E =0001=9E de otra manera, da igual la posicion del numero su suma de verificacion siempre es la misma. gracias por la ayuda de nuevo
Con que estas trabajando.
Son mensajes de que?