Ви не увійшли.
Посмотри может информация поможет
http://tim4dev.com/2016/03/arduino-rabota-s-sd-microsd-kartami/
Вроде-бы, на Arduino Leonardo 1 шина SPI. На Mega и Due - по 2. А для чтения SD-карт используется SPI. И вы также используете SPI. Внимательно почитайте документацию.
а эти платы совместимы по уровням сигналов? проверь, потому что RF522 вообще питается от +3V но работает с UNO на +5V, но записать скетч по SPI при подключенном RF522 я не могу приходиться отключать RFID, может такая же проблема есть и при совместной работе Логера + RFIDa + Arduino...
Да SS используется....
а кстати провод SS используется? без него работать точно не будет
Я подключал к SPI радиомодуль, который очень прекрасно работал, но при этом программатор для меги, подключаемый тоже к SPI упорно не хотел видеть контроллер. Пришлось вынять из постели модуль, залить загрузчик и дальше работать по юарту. Факт взаимных помех подтвердаю.
> По отдельности два скетча работают.
Возможно не хватает оперативной памяти. При вызове методов библиотек могут создаваться обьекты в куче, которые не учитываются при компилировании.
Доброго дня!
Собираю контроллер для автомойки самообслуживания. В принципе уже есть рабочий вариант, но решил добавить запись логов на SD карту.
В составе рабочего модуля:
arduino Leonardo.
7segment shield - 2шт - каждый на отдельной плате с процессором
RC522 - RFID считыватель для карт
Купюроприёмник - выдаёт имульсы.
Все шилды подключены по "железному" SPI паралельно т.к. на леонардо они не дублируются на выводы и вообще чтоб пины не забивать У каждого свой SS.
Вот работающий скетч:
/*
* MFRC522 - Library to use ARDUINO RFID MODULE KIT 13.56 MHZ WITH TAGS SPI W AND R BY COOQROBOT.
* The library file MFRC522.h has a wealth of useful info. Please read it.
* The functions are documented in MFRC522.cpp.
*
* Based on code Dr.Leong ( WWW.B2CQSHOP.COM )
* Created by Miguel Balboa (circuitito.com), Jan, 2012.
* Rewritten by Søren Thing Andersen (access.thing.dk), fall of 2013 (Translation to English, refactored, comments, anti collision, cascade levels.)
*
* Released into the public domain.
*
* This sample shows how to setup a block on a MIFARE Classic PICC to be in "Value Block" mode.
* In Value Block mode the operations Increment/Decrement/Restore and Transfer can be used.
*
----------------------------------------------------------------------------- empty_skull
- Aggiunti pin per arduino Mega
- Scritto semplice codice per la scrittura e lettura
- add pin configuration for arduino mega
- write simple read/write Code for new entry user
http://mac86project.altervista.org/
----------------------------------------------------------------------------- Nicola Coppola
* Pin layout should be as follows:
* Signal Pin Pin Pin
* Arduino Uno Arduino Mega MFRC522 board
* ------------------------------------------------------------
* Reset 9 5 RST
* SPI SS 10 53 SDA
* SPI MOSI 11 51 MOSI
* SPI MISO 12 50 MISO
* SPI SCK 13 52 SCK
*
* The reader can be found on eBay for around 5 dollars. Search for "mf-rc522" on ebay.com.
*/
// в этой версии деньги списывалсь сами при подключении к плате SD1
#include <SPI.h>
#include <MFRC522.h>
#define SS_PIN 6
#define RST_PIN 5
//ОБЪЯВЛЯЕМ ПЕРЕМЕННЫЕ
int ON = LOW; //Переопределяем значения цифровых входов
int OFF = HIGH; //Переопределяем значения цифровых входов
int Money; //переменная для подсчёта денег на карте
int FullSumm = 0; //Сумма денег на мойке
int WaterCost = 125 ; //"Цена" воды (миллисекунд на рубль)
int FoamCost = 25; //"Цена" пены (миллисекунд на рубль)
byte LastCardUid[10]; //Идентификатор последней карты - массив из 10ти переменных типа byte
boolean CardsIdentical; //Новая карта
int tmpmoney = OFF; //Временная переменная для счетчика импульсов
int impMoney = 0; //Импульсы от купюроприемника
long oldtime = 0; //Время, прошедшее с последнего импульса
int tmpPump = OFF; //Временная переменная работы НВД
long oldMillis = 0; //Временная переменная для списывания денег
long WorkingTime = 0; //Время работы НВД
boolean SummMustShow = false; //Флаг обновления экрана для показа суммы
boolean IsFoam = false; //Флаг вода/пена
int tmp = 0;
int led4 = 9;
int led3 = 11;
//int led2 = 3; // отключил для экранов
//int led1 = 2; // отключил для экранов
int tmp2 = 0;
MFRC522 mfrc522(SS_PIN, RST_PIN); // Create MFRC522 instance.
int Disp1 = 3; //экран
void setup() {
//подтягиваем резисторы. теперь что бы подать сигнал на 11 и 13 нужно замкнуть их на землю
digitalWrite(12, HIGH);
digitalWrite(13, HIGH);
digitalWrite(8, HIGH);
Serial.begin(9600); // Initialize serial communications with the PC
SPI.begin(); // Init SPI bus
mfrc522.PCD_Init(); // Init MFRC522 card
//Serial.println("Scan a MIFARE Classic PICC to demonstrate Value Blocks.");
//Для купюроприемника
pinMode(7, OUTPUT); //команда разрешения на прием купюр
digitalWrite(7, HIGH); //Подтягиваем резистор теперь отсутствие сигнала - HIGH, присутствие - LOW
pinMode(4, INPUT); //Счетчик купюр
digitalWrite(4, HIGH); //Подтягиваем резистор теперь отсутствие сигнала - HIGH, присутствие - LOW
//Датчики протока пены
pinMode(8, INPUT); //Датчик протекания воды
//digitalWrite(2, HIGH); //Подтягиваем резистор теперь отсутствие сигнала - HIGH, присутствие - LOW
//Датчики работы насоса
pinMode(2, INPUT); //Датчик протекания воды
//digitalWrite(2, HIGH); //Подтягиваем резистор теперь отсутствие сигнала - HIGH, присутствие - LOW
//pinMode(led1, OUTPUT);
//pinMode(led2, OUTPUT);
pinMode(led3, OUTPUT);
pinMode(led4, OUTPUT);
//экран--------------
pinMode(Disp1, OUTPUT); //Экран №1
digitalWrite(Disp1, HIGH); //Отключаем пока
SPI.setClockDivider(SPI_CLOCK_DIV64);
ShowString("-00-", Disp1);
}
void loop() {
if (FullSumm > 0) {
digitalWrite(led3, HIGH); //если на мойке есть деньги, замыкаем цепь разрешение работы насоса
}
else digitalWrite(led3, LOW);
tmp2 = digitalRead(2); //
Serial.print(tmp2);
//if (digitalRead(10)==ON){
// Serial.print("pena");
// }
tmp = digitalRead(4); //считываем значение порта 4 к которому подключён pulse с купюроприёмника считаем деньгу
if (tmp != tmpmoney){ //если значение на входе 4 менялось
impMoney++; //увеличиваем счётчик изменений на 1
tmpmoney = tmp; //отмечаем на какое значение менялось значение на входе 4
oldtime = millis(); //запоминаем когда было последнее изменение
}
//Serial.print(impMoney);
if ((millis()-oldtime) > 500 && (millis()-oldtime) < 530){
FullSumm = FullSumm+(impMoney*5); //?если импульсы с купюроприёмника не поступают 500 милисекунд то добавляем сосчитанные импульсы к сумме....
impMoney = 0; //обнуляем счётчик импульсов т.к. всё посчетали
SummMustShow = true; //разрешаем показать сумму
}
//Показываем сумму
if (SummMustShow == true){ //если показать сумму можно
Serial.print(FullSumm);
ShowValue(FullSumm, Disp1); //вывод на дисплей
SummMustShow = false; //запрет показа суммы
//Serial.println("Full summ is: "+FullSumm); //?увеличивает значение на дисплее на FullSumm - сколько зачислили в купюроприёмник
}
//Смотрим переключатель вода/пена
if (digitalRead(8) == OFF){ //данный переключатель почемуто работает наоборот а на 13-м не работает наверное это связано со втроеным резистором на 13-м
IsFoam = false;
}
else IsFoam = true;
//Списываем деньги
if ((digitalRead(12)== ON)&&(FullSumm > 0)){ //? если реле потока даёт сигнал и на мойке ещё есть деньги
if (oldMillis < millis()){ // то
WorkingTime++;
oldMillis = millis();
}
if ((WorkingTime%WaterCost == 0) && (IsFoam==false)) { //если прошло ещё достаточно милисекунд для списания рублика за воду и пена выключена то списываем рублик за воду
FullSumm--;
SummMustShow = true;
WorkingTime = 1;
}
if ((WorkingTime%FoamCost == 0) && (IsFoam==true)) { //если прошло ещё достаточно милисекунд для списания рублика за пену и пена влючена то списываем рублик за пену
FullSumm--;
SummMustShow = true;
WorkingTime = 1;
}
}
//Работа с картами___________________________________________________________________
// Prepare key - all keys are set to FFFFFFFFFFFFh at chip delivery from the factory.
MFRC522::MIFARE_Key key;
for (byte i = 0; i < 6; i++) {
key.keyByte[i] = 0xFF;
}
// Look for new cards
if ( ! mfrc522.PICC_IsNewCardPresent()) {
return;
}
// Select one of the cards
if ( ! mfrc522.PICC_ReadCardSerial()) {
return;
}
// Now a card is selected. The UID and SAK is in mfrc522.uid.
// Dump UID
Serial.print("Card UID:");
for (byte i = 0; i < mfrc522.uid.size; i++) {
Serial.print(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " ");
Serial.print(mfrc522.uid.uidByte[i], HEX);
}
Serial.println();
// Dump PICC type
byte piccType = mfrc522.PICC_GetType(mfrc522.uid.sak);
Serial.print("PICC type: ");
Serial.println(mfrc522.PICC_GetTypeName(piccType));
if ( piccType != MFRC522::PICC_TYPE_MIFARE_MINI
&& piccType != MFRC522::PICC_TYPE_MIFARE_1K
&& piccType != MFRC522::PICC_TYPE_MIFARE_4K) {
//Serial.println("This sample only works with MIFARE Classic cards.");
return;
}
// In this sample we use the second sector (ie block 4-7). the first sector is = 0
// scegliere settore di lettura da 0 = primo settore
byte sector = 1;
// block sector 0-3(sector0) 4-7(sector1) 8-11(sector2)
// blocchi di scrittura da 0-3(sector0) 4-7(sector1) 8-11(sector2)
byte valueBlockA = 4;
byte valueBlockB = 5;
byte valueBlockC = 6;
byte trailerBlock = 7;
byte status;
// Authenticate using key A.
// avvio l'autentificazione A
//Serial.println("Authenticating using key A...");
status = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, trailerBlock, &key, &(mfrc522.uid));
if (status != MFRC522::STATUS_OK) {
Serial.print("PCD_Authenticate() failed: ");
Serial.println(mfrc522.GetStatusCodeName(status));
return;
}
// Authenticate using key B.
// avvio l'autentificazione B
//Serial.println("Authenticating again using key B...");
status = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_B, trailerBlock, &key, &(mfrc522.uid));
if (status != MFRC522::STATUS_OK) {
Serial.print("PCD_Authenticate() failed: ");
Serial.println(mfrc522.GetStatusCodeName(status));
return;
}
/*
// Writing new value block A
// Scrivo i valori per il settore A
Serial.println("Writing new value block A(4) : the first of the sector TWO ");
byte value1Block[] = { 1,2,3,4, 5,6,7,8, 9,10,255,12, 13,14,15,16, valueBlockA,~valueBlockA,valueBlockA,~valueBlockA };
status = mfrc522.MIFARE_Write(valueBlockA, value1Block, 16);
if (status != MFRC522::STATUS_OK) {
Serial.print("MIFARE_Write() failed: ");
Serial.println(mfrc522.GetStatusCodeName(status));
}
/*
// Writing new value block B
// Scrivo i valori per il settore B
Serial.println("Writing new value block B");
byte value2Block[] = { 255,255,255,255, 0,0,0,0, 0,0,0,0, 255,255,255,255, valueBlockB,~valueBlockB,valueBlockB,~valueBlockB };
status = mfrc522.MIFARE_Write(valueBlockB, value2Block, 16);
if (status != MFRC522::STATUS_OK) {
Serial.print("MIFARE_Write() failed: ");
Serial.println(mfrc522.GetStatusCodeName(status));
}
// Writing new value block D
// Scrivo i valori per il settore C
Serial.println("Writing new value block C");
byte value3Block[] = { 255,255,255,255, 0,0,0,0, 0,0,0,0, 255,255,255,255, valueBlockC,~valueBlockC,valueBlockC,~valueBlockC };
status = mfrc522.MIFARE_Write(valueBlockC, value3Block, 16);
if (status != MFRC522::STATUS_OK) {
Serial.print("MIFARE_Write() failed: ");
Serial.println(mfrc522.GetStatusCodeName(status));
}
*/
Serial.println("Read block A(4) : the first of the sector TWO");
byte buffer[18];
byte size = sizeof(buffer);
// change this: valueBlockA , for read anather block
// cambiate valueBlockA per leggere un altro blocco
status = mfrc522.MIFARE_Read(valueBlockA, buffer, &size);
Money = buffer[0]*256+buffer[1]; //считывание денег из блока А и записть их в переменную Money
Serial.print("Money on card: ");
Serial.println(Money); //вывод на порт суммы денег на карте
Serial.println("Read cardholder name:");
status = mfrc522.MIFARE_Read(valueBlockB, buffer, &size);
for (byte i = 0; i < 16; i++){
Serial.print(char(buffer[i])); //вывод на порт имени держателя карты поэлементно из массива buffer
}
Serial.println(); // перенос cтрочки при выводе данных на порт
/*
if (FullSumm == 0){
//Сумма в мойке равна 0
if (!CardsIdentical){
//Карта уже отмечалась перед этим
FullSumm = Money;//забрали деньги с карты на мойку можно написать FullSumm = FullSumm + Money; тогда деньги на мойке и на карте сложаться
Money = 0;
// SummMustShow = true;
}
}
else {
//Сумма в мойке больше 0
if (!CardsIdentical){
//Карта уже отмечалась перед этим
//так было FullSumm = Money; //забрали деньги с карты на мойку можно написать FullSumm = FullSumm + Money; тогда деньги на мойке и на карте сложаться
FullSumm = FullSumm + Money;
Money = 0; //деньги на карте обнулили
}
else{
Money = FullSumm; //забрали деньги с мойки на карту
FullSumm = 0; //обнулли деньги на мойке
}
SummMustShow = true; //флаг обновления данных на дисплее
}
*/
Serial.print("FullSumm do:");
Serial.print(FullSumm);
Serial.println();
Serial.print("Money do:");
Serial.print(Money);
Serial.println();
if (FullSumm >= 0 && Money > 0 && SummMustShow != true ){ //флаг SummMustShow используется для того что бы выполнялось только одно из условий для перевода денег с карты на мойку или наоборот
FullSumm = FullSumm + Money;
Money = 0;
SummMustShow = true;
Serial.println("skinuli dengi s karti");
}
if (FullSumm > 0 && Money == 0 && SummMustShow != true ){ //флаг SummMustShow используется для того что бы выполнялось только одно из условий для перевода денег с карты на мойку или наоборот
Money = FullSumm ;
FullSumm = 0;
SummMustShow = true;
Serial.println("skinuli dengi na kartu");
}
Serial.print("FullSumm posle:");
Serial.print(FullSumm);
Serial.println();
Serial.print("Money posle:");
Serial.print(Money);
Serial.println();
//Записываем на карту сумму либо добавляя то что осталось на карту, либо пишем ноль если забирали деньги с карты
Serial.println("Writing ");
byte value1Block[] = {byte(Money/256),byte(Money%256),0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, valueBlockA,~valueBlockA,valueBlockA,~valueBlockA };
status = mfrc522.MIFARE_Write(valueBlockA, value1Block, 16);
if (status != MFRC522::STATUS_OK) {
Serial.print("MIFARE_Write() failed: ");
Serial.println(mfrc522.GetStatusCodeName(status));
}
Serial.println("pobitno blok A:");
status = mfrc522.MIFARE_Read(valueBlockA, buffer, &size);
for (byte i = 0; i < 16; i++){
Serial.print(byte(buffer[i])); //вывод на порт побитно значений из блока А
}
Serial.println(); // перенос cтрочки при выводе данных на порт
// risponde successo
//Serial.println(mfrc522.GetStatusCodeName(status));
// Dump the result
//mfrc522.PICC_DumpMifareClassicSectorToSerial(&(mfrc522.uid), &key, sector);
// Halt PICC
mfrc522.PICC_HaltA();
// Stop encryption on PCD
mfrc522.PCD_StopCrypto1();
}
void ShowValue(int tempCycles, int Pin)
{
char Str[4];
boolean ShowZeros = false;
if (tempCycles >= 10000){
return;
}
if (tempCycles/1000 > 0){
Str[0] = tempCycles/1000;
ShowZeros = true;
}
else Str[0] = 32;
tempCycles %= 1000;
if ((tempCycles/100 > 0)||(ShowZeros)){
Str[1] = tempCycles/100;
ShowZeros = true;
}
else Str[1] = 32;
tempCycles %= 100;
if ((tempCycles/10 > 0)||(ShowZeros)){
Str[2] = tempCycles/10;
ShowZeros = true;
}
else Str[2] = 32;
tempCycles %= 10;
Str[3] = tempCycles;
ShowString(Str, Pin);
}
void ShowString(char *toSend, int Pin){
digitalWrite(Pin, LOW); //Включаем передачу для выбранного пина
SPI.transfer('v');
for(byte x = 0; x < 4; x++)
SPI.transfer(toSend[x]); //Send a character from the array out over SPI
digitalWrite(Pin, HIGH); //Выключаем передачу для выбранного пина
}
Теперь подключил Data logging shield v1.0 (на нём шина SPI заточена под UNO, я перепаял ноги 11,12,13 на железные выводы miso/mosi/sck)
Написал отдельный скетч на базе примера из библиотеки SD для сохранения в файл данных переменной Fullsumm и чтения этих данных из файла при перезагрузке контроллера.
вот скетч:
/*
SD card read/write
This example shows how to read and write data to and from an SD card file
The circuit:
* SD card attached to SPI bus as follows:
** UNO: MOSI - pin 11, MISO - pin 12, CLK - pin 13, CS - pin 4 (CS pin can be changed)
and pin #10 (SS) must be an output
** Mega: MOSI - pin 51, MISO - pin 50, CLK - pin 52, CS - pin 4 (CS pin can be changed)
and pin #52 (SS) must be an output
** Leonardo: Connect to hardware SPI via the ICSP header
created Nov 2010 by David A. Mellis
modified 9 Apr 2012 by Tom Igoe
This example code is in the public domain.
*/
#include <SPI.h>
#include <SD.h>
File myFile;
// change this to match your SD shield or module;
// Arduino Ethernet shield: pin 4
// Adafruit SD shields and modules: pin 10
// Sparkfun SD shield: pin 8
const int chipSelect = 10;
//byte FullSumm = 3000;
int FullSumm = 30000;
byte t1;
byte t2;
int t3;
// byte start;
int start;
void setup()
{
// Open serial communications and wait for port to open:
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for Leonardo only
}
Serial.print("Initializing SD card...");
// On the Ethernet Shield, CS is pin 4. It's set as an output by default.
// Note that even if it's not used as the CS pin, the hardware SS pin
// (10 on most Arduino boards, 53 on the Mega) must be left as an output
// or the SD library functions will not work.
pinMode(SS, OUTPUT);
if (!SD.begin(chipSelect)) {
Serial.println("initialization failed!");
return;
}
Serial.println("initialization done.");
// open the file. note that only one file can be open at a time,
// so you have to close this one before opening another.
// мои код
myFile = SD.open("test.txt"); //открывает файл test.txt
//Money = buffer[0]*256+buffer[1]; //считывание денег из блока А и записть их в переменную Money
// myFile.seek(0);
// t1 = myFile.read();
// Serial.println(t1);
// t2 = myFile.read();
// Serial.println(t2);
//t3 = t1*256 + t2 ;
// start = t3;
start = (myFile.read())*256 + myFile.read() ; //читаем первый и второй байт в переменную start
Serial.println(start); //выводим на серийный порт значение переменной старт
myFile.close();
//мой код
myFile = SD.open("test.txt", FILE_WRITE);
// if the file opened okay, write to it:
if (myFile) {
Serial.print("Writing to test.txt...");
myFile.seek(0); //чтобы записывать с позиции 0
myFile.write( byte (FullSumm/256));
myFile.write( byte (FullSumm%256));
// byte(Money/256),byte(Money%256)
// close the file:
myFile.close();
Serial.println("done.");
} else {
// if the file didn't open, print an error:
Serial.println("error opening test.txt");
}
// re-open the file for reading:
myFile = SD.open("test.txt");
if (myFile) {
Serial.write("test.txt:");
// read from the file until there's nothing else in it:
while (myFile.available()) {
Serial.write(myFile.read());
}
// close the file:
myFile.close();
} else {
// if the file didn't open, print an error:
Serial.println("error opening test.txt");
}
}
void loop()
{
// nothing happens after setup
}
По отдельности два скетча работают.
При обьединении компилятор ошибок не выдаёт, но вот устройства по SPI перестают работать. Экран выдаёт кракозябры, считыватель карт не работает, Serial выдаёт тишину.
Опытным путём, добавляя в основной скетч по отдельности разные строики из скетча чтение\запись что проблемы начинаются после добавления строки:
#include <SD.h>
Открыв данную библиотеку и почитав её описание обнаружил:
1.для леонардо есть особая версия библиотеки в которой в ручную виртуально привязываются выводы SPI к 11,12,13 пину. Я эту проблему решил перепайкой данных портов на железную шину SPI (которая сбоку из шести контактов)
2.в теле библиотеки есть строчка return card.init(SPI_HALF_SPEED, csPin, mosi, miso, sck) && volume.init(card) && root.openRoot(volume);
предполагаю что модуль для SD карт работает на другой частоте шины SPI. но вот как разрешить проблему работы нескольких устройств по одной шине SPI ума не приожу... Они ведь все нужны.
Читал про продвинутые натройки шины SPI на DUO... но вот приобрести DUO по ка нет возможности...
Уважаемые Гуру, прошу подсказать:
1. Верны ли мои предположения?
2. Какие путы выхода из ситуации возможны?
Если нужна какая то дополнительная информация - готов предоставить. Спасибо.