I'm trying to implement "one wire" for ChibiOS, running on atmega1280 (Arduino board). I am mostly copy/pasting from the arduino implementation (which works fine):
uint8_t OneWire::reset(void)
{
IO_REG_TYPE mask = bitmask;
volatile IO_REG_TYPE *reg IO_REG_ASM = baseReg;
uint8_t r;
uint8_t retries = 125;
noInterrupts();
DIRECT_MODE_INPUT(reg, mask);
interrupts();
// wait until the wire is high... just in case
do {
if (--retries == 0) return 0;
delayMicroseconds(2);
} while ( !DIRECT_READ(reg, mask));
noInterrupts();
DIRECT_WRITE_LOW(reg, mask);
DIRECT_MODE_OUTPUT(reg, mask); // drive output low
interrupts();
delayMicroseconds(480);
noInterrupts();
DIRECT_MODE_INPUT(reg, mask); // allow it to float
delayMicroseconds(70);
r = !DIRECT_READ(reg, mask);
interrupts();
delayMicroseconds(410);
return r;
}
What I wrote for the ChibiOS implementation of the "reset" function is the following:
uint8_t OneWire::reset(void)
{
palSetPadMode((ioportid_t)IOPORT2, 3, PAL_MODE_INPUT);
// Wait until the wire is high.
uint8_t retries = 125;
do {
if (--retries == 0) {
return 0;
}
chThdSleepMicroseconds(2);
} while (palReadPad(IOPORT2, 3) == PAL_LOW);
palSetPadMode((ioportid_t)IOPORT2, 3, PAL_MODE_OUTPUT_PUSHPULL);
palWritePad(IOPORT2, 3, PAL_LOW); // drive output low
chThdSleepMicroseconds(480);
palSetPadMode((ioportid_t)IOPORT2, 3, PAL_MODE_INPUT);
chThdSleepMicroseconds(70);
uint8_t result = (palReadPad(IOPORT2, 3) == PAL_LOW);
chThdSleepMicroseconds(410);
return result;
}
What am I doing wrong?
Related
I am trying to set the timer after which the audio will automatically played once but it is not playing anything just a noise but when i run the audio program separately it work perfectly good
This is my code please help me out where i am doing wrong.
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <SD.h>
#include <TMRpcm.h>
#include <SPI.h>
int timer1_counter;
#define SD_ChipSelectPin 4
TMRpcm tmrpcm;
unsigned long time_now = 0;
LiquidCrystal_I2C lcd(0x27, 16, 2);
const byte ledPin = 13;
const byte interruptPin1 = 2;
const byte interruptPin2 = 3;
int counter2 = 0;
volatile byte state = LOW;
int count = 0;
int limit = 0;
bool TimerFlag = false;
int deviceTime = 0;
int set = 5;
bool soundplayflag = false;
void setup()
{
lcd.begin();
Serial.begin(9600);
pinMode(ledPin, OUTPUT);
pinMode(interruptPin1, INPUT_PULLUP);
pinMode(interruptPin2, INPUT_PULLUP);
pinMode(set, INPUT_PULLUP);
lcd.backlight();
lcd.setCursor(1,0);
lcd.print("Please Select:");
noInterrupts(); // disable all interrupts
TCCR1A = 0;
TCCR1B = 0;
TCNT1 = 0;
OCR1A = 31250; // compare match register 16MHz/256/2Hz
TCCR1B |= (1 << WGM12); // CTC mode
TCCR1B |= (1 << CS12); // 256 prescaler
TIMSK1 |= (1 << OCIE1A); // enable timer compare interrupt
interrupts(); // enable all interrupts
// initialize timer1
}
ISR(TIMER1_COMPA_vect) // timer compare interrupt service routine
{
if (soundplayflag == true)
{
counter2 = counter2+1;
Serial.println(counter2/2);
}
}
void loop()
{
//unsigned long currentMillis = millis();
int up = digitalRead(interruptPin1);
int down = digitalRead(interruptPin2);
int setbutton = digitalRead(set);
delay(230);
if (up == 0)
{
Serial.println("Entering up");
count++;
if (count >= 0) {
lcdprint(count);
}
}
else if (down == 0)
{
Serial.println("Entering down");
count--;
if (count >= 0) {
lcdprint(count);
}
}
else if (setbutton == 0)
{
Serial.println("Entering set");
soundplayflag=true;
deviceTime = count;
}
if (deviceTime > 0)
{
if (deviceTime == counter2)
{
soundplayflag=false;
Serial.println("Hello world");
PlaySound();
counter2 = 0;
}
}
}
int lcdprint(int a)
{
lcd.clear();
lcd.setCursor(1,0);
lcd.print("Please Select:");
lcd.setCursor (7,1);
lcd.print(a);
Serial.println(a);
lcd.setCursor (10,1);
lcd.print("Min");
}// end of lcdprint(int a)
void PlaySound()
{
for (int i = 0; i < 10; i++)
{
tmrpcm.setVolume(5);
tmrpcm.play("3.wav");
delay(1000);
}// end of for loop
}// end of void PlaySound()
my expected output is it should play the sound when i set the time
It seems TMRpcm uses Timer1, which conflicts with your TIMER1_COMPA_vect. That would explain why it's working if you run nothing else.
Maybe try to use #define USE_TIMER2?
My goal is to transfer a speed value from an encoder from a slave Arduino to a master Arduino via SPI. I am currently getting zeros on the master side serial print and I'm not sure what I am doing wrong. I have increased the amount of time to wait several times to see if it was a processing time issue but I had it waiting for 100mS with still no change. I know an unsigned int is 4 bytes and I am unsure if a union is the best option in this case seeing I might be overwriting my data due to the separate interrupts but I am unsure. I thought to use a struct since I'll have to move to transferring an array of floats and ints over SPI from various sensors including this encoder later. Below is my code and thank you for any help received:
Slave
#include "math.h"
#define M_PI
byte command = 0;
const int encoder_a = 2; // Green - pin 2 - Digital
const int encoder_b = 3; // White - pin 3 - Digital
long encoder = 0;
int Diameter = 6; // inches
float previous_distance = 0;
unsigned long previous_time = 0;
void setup (void)
{
Serial.begin(115200);
pinMode(MOSI, INPUT);
pinMode(SCK, INPUT);
pinMode(SS, INPUT);
pinMode(MISO, OUTPUT);
// turn on SPI in slave mode
SPCR |= _BV(SPE);
// turn on interrupts
SPCR |= _BV(SPIE);
pinMode(encoder_a, INPUT_PULLUP);
pinMode(encoder_b, INPUT_PULLUP);
attachInterrupt(0, encoderPinChangeA, CHANGE);
attachInterrupt(1, encoderPinChangeB, CHANGE);
}
// SPI interrupt routine
ISR (SPI_STC_vect)
{
union Data{
float f;
byte buff[4];}
data;
byte c = SPDR;
data.f = assembly_speed();
command = c;
switch (command)
{
// no command? then this is the command
case 0:
SPDR = 0;
break;
// incoming byte, return byte result
case 'a':
SPDR = data.buff[0];
break;
// incoming byte, return byte result
case 'b':
SPDR = data.buff[1];
break;
// incoming byte, return byte result
case 'c':
SPDR = data.buff[2];
break;
// incoming byte, return byte result
case 'd':
SPDR = data.buff[3];
break;
}
}
void loop (void)
{
// if SPI not active, clear current command
if (digitalRead (SS) == HIGH)
command = 0;
}
void encoderPinChangeA()
{
encoder += digitalRead(encoder_a) == digitalRead(encoder_b) ? -1 : 1;
}
void encoderPinChangeB()
{
encoder += digitalRead(encoder_a) != digitalRead(encoder_b) ? -1 : 1;
}
float distance_rolled()
{
float distance_traveled = (float (rotation()) / 8) * PI * Diameter;
return distance_traveled;
}
int rotation()
{
float eigth_rotation = encoder / 300;
return eigth_rotation;
}
float assembly_speed()
{
float current_distance = (float (rotation()) / 8) * PI * Diameter;
unsigned long current_time = millis();
unsigned long assemblySpeed = (((current_distance - previous_distance) /
12) * 1000) / (current_time - previous_time); // gives ft/s
previous_distance = current_distance;
previous_time = current_time;
return assemblySpeed;
}
Master
#include <SPI.h>
void setup (void)
{
pinMode(MOSI, OUTPUT);
pinMode(MISO, INPUT);
pinMode(SCK, OUTPUT);
pinMode(SS, OUTPUT);
Serial.begin (115200);
Serial.println ();
digitalWrite(SS, HIGH);
SPI.begin ();
SPI.setClockDivider(SPI_CLOCK_DIV8);
}
byte transferAndWait (const byte what)
{
byte a = SPI.transfer (what);
delayMicroseconds(10000);
return a;
}
union Data
{
float f;
byte buff[4];
}
data;
void loop (void)
{
digitalWrite(SS, LOW);
transferAndWait ('a');
data.buff[0] = transferAndWait ('b');
data.buff[1] = transferAndWait ('c');
data.buff[2] = transferAndWait ('d');
data.buff[3] = transferAndWait (0);
digitalWrite(SS, HIGH);
Serial.print("data.f = ");Serial.print(data.f);Serial.println(" Ft/s");
delay(200);
}
I'm using an arduino uno with a CC3000 WiFi Shield. The ardunio counts people using a light barrier and then reports the countings to the xievly site. It seems to work fine for an hour or two but then nothing happens. Any ideas?
// Libraries
#include <Adafruit_CC3000.h>
#include <SPI.h>
#include <Time.h>
#include <TimeAlarms.h>
// Define CC3000 chip pins
#define ADAFRUIT_CC3000_IRQ 3
#define ADAFRUIT_CC3000_VBAT 5
#define ADAFRUIT_CC3000_CS 10
// Create CC3000 instances
Adafruit_CC3000 cc3000 = Adafruit_CC3000(ADAFRUIT_CC3000_CS, ADAFRUIT_CC3000_IRQ, ADAFRUIT_CC3000_VBAT,
SPI_CLOCK_DIV2); // you can change this clock speed
// WLAN parameters
#define WLAN_SSID "XX"
#define WLAN_PASS "XX"
#define WLAN_SECURITY WLAN_SEC_WPA2
// Xively parameters
#define WEBSITE "https://xively.com/feeds/XX"
#define API_key "XXX"
#define feedID "XXXX``"
uint32_t ip;
Adafruit_CC3000_Client client;
const unsigned long
connectTimeout = 15L * 1000L, // Max time to wait for server connection
responseTimeout = 15L * 1000L; // Max time to wait for data from server
// Visitor Counter
int anzahl =0;
int lastState=LOW;
const int inputPin = 2;
void setup()
{
// Initialize
attachInterrupt(0, count, RISING);
Serial.begin(115200);
if (!cc3000.begin())
{
while(1);
}
// Connect to WiFi network
cc3000.connectToAP(WLAN_SSID, WLAN_PASS, WLAN_SECURITY);
/* Wait for DHCP to complete */
while (!cc3000.checkDHCP())
{
delay(100);
}
unsigned long t = getTime();
cc3000.disconnect();
setTime(hour(t)+2,minute(t),second(t),month(t),day(t),year(t));
Alarm.alarmRepeat(9,59,59, Messung);
Alarm.alarmRepeat(10,59,59, Messung);
Alarm.alarmRepeat(11,59,59, Messung);
Alarm.alarmRepeat(12,59,59, Messung);
Alarm.alarmRepeat(13,59,59, Messung);
Alarm.alarmRepeat(14,59,59, Messung);
Alarm.alarmRepeat(15,59,59, Messung);
Alarm.alarmRepeat(16,59,59, Messung);
Alarm.alarmRepeat(17,59,59, Messung);
Alarm.alarmRepeat(18,59,59, Messung);
Alarm.alarmRepeat(19,59,59, Messung);
Alarm.alarmRepeat(22,59,59, Zeitkorrektur);
}
void count()
{
delay(10);
int val = digitalRead(inputPin);
if (val == HIGH && lastState==LOW)
{
anzahl++;
lastState=val;
}
else
{
lastState=val;
}
}
void Zeitkorrektur()
{
getTime();
}
void Messung()
{
datalog();
}
void loop()
{
Alarm.delay(1000);
}
// Minimalist time server query; adapted from Adafruit Gutenbird sketch,
// which in turn has roots in Arduino UdpNTPClient tutorial.
unsigned long getTime()
{
uint8_t buf[48];
unsigned long ip, startTime, t = 0L;
// Hostname to IP lookup; use NTP pool (rotates through servers)
if(cc3000.getHostByName("pool.ntp.org", &ip)) {
static const char PROGMEM
timeReqA[] = { 227, 0, 6, 236 },
timeReqB[] = { 49, 78, 49, 52 };
Serial.println(F("\r\nAttempting connection..."));
startTime = millis();
do {
client = cc3000.connectUDP(ip, 123);
} while((!client.connected()) &&
((millis() - startTime) < connectTimeout));
if(client.connected()) {
Serial.print(F("connected!\r\nIssuing request..."));
// Assemble and issue request packet
memset(buf, 0, sizeof(buf));
memcpy_P( buf , timeReqA, sizeof(timeReqA));
memcpy_P(&buf[12], timeReqB, sizeof(timeReqB));
client.write(buf, sizeof(buf));
Serial.print(F("\r\nAwaiting response..."));
memset(buf, 0, sizeof(buf));
startTime = millis();
while((!client.available()) &&
((millis() - startTime) < responseTimeout));
if(client.available()) {
client.read(buf, sizeof(buf));
t = (((unsigned long)buf[40] << 24) |
((unsigned long)buf[41] << 16) |
((unsigned long)buf[42] << 8) |
(unsigned long)buf[43]) - 2208988800UL;
Serial.print(F("OK\r\n"));
}
client.close();
}
}
if(!t) Serial.println(F("error"));
return t;
}
void datalog()
{
//noInterrupts();
// Connect to WiFi network
cc3000.connectToAP(WLAN_SSID, WLAN_PASS, WLAN_SECURITY);
/* Wait for DHCP to complete */
while (!cc3000.checkDHCP())
{
delay(100);
}
// Set the website IP
uint32_t ip = cc3000.IP2U32(216,52,233,120);
cc3000.printIPdotsRev(ip);
// Get data & transform to integers
int visitors = (int) anzahl/2; //Visitors going in and out therefore divided by 2
// Prepare JSON for Xively & get length
int length = 0;
String data = "";
data = data + "\n" + "{\"version\":\"1.0.0\",\"datastreams\" : [ {\"id\" : \"Visitors\",\"current_value\" : \"" + String(visitors) + "\"}]}";
length = data.length();
// Send request
Adafruit_CC3000_Client client = cc3000.connectTCP(ip, 80);
if (client.connected()) {
Serial.println("Connected!");
client.println("PUT /v2/feeds/" + String(feedID) + ".json HTTP/1.0");
client.println("Host: api.xively.com");
client.println("X-ApiKey: " + String(API_key));
client.println("Content-Length: " + String(length));
client.print("Connection: close");
client.println();
client.print(data);
client.println();
} else {
Serial.println(F("Connection failed"));
return;
}
Serial.println(F("-------------------------------------"));
while (client.connected()) {
while (client.available()) {
char c = client.read();
Serial.print(c);
}
}
client.close();
Serial.println(F("-------------------------------------"));
Serial.println(F("\n\nDisconnecting"));
cc3000.disconnect();
anzahl =0;
//interrupts();
}
In setup() you configured interrupt with RISING. That means that it fires when the pin goes from low state to high state. But in interrupt handler - count() you have strange logic which looks excessive since you already configured interrupt to fire only once on event.
Let's see what happens in count(). val will always be HIGH (well, considering only normal case, not glitches).. When the first interrupt comes lastState is LOW as initial value and we increment, but all successive calls will not because lastState is HIGH and never becomes LOW again.
So, to fix problem, we simply need to drop lastState because it's not needed
void count()
{
delay(10);
// avoiding glitches - check if it's still high
int val = digitalRead(inputPin);
if (val == HIGH)
anzahl++;
}
I have an application where I am using a MCP3421 18bit ADC to read analog data. The setup is Xbee+Xbee Sheild+Arduino + MCP3421 as Transmitter. This I am reading and transmitting to a remote xbee+arduino module with LCD. The data is displayed fine on the LCD. however I want to receive the data on the Serial port. When i try tp Do a Serial.println(s); on the receiving code the data which i get on serial port is garbled. Would appreciate any help
Here is my Code
Transmitting
#include <Wire.h>
#include <LiquidCrystal.h>
#define TRUE 1
#define FALSE 0
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
void setup(void)
{
Serial.begin(9600);
Wire.begin();
delay(100);
Serial.println(">>>>>>>>>>>>>>>>>>>>>>>>"); // just to be sure things are working
lcd.begin(16, 2);
}
void loop(void)
{
byte address, Hi, Lo, Config;
int ADVal;
while(1)
{
address = 0x68;
Wire.beginTransmission(address);
Wire.write(0x88); // config register %1000 1000
// /RDY = 1, One Conversion, 15 samples per, PGA = X1
Wire.endTransmission();
delay(1);
Wire.requestFrom((int)address, (int) 3);
Hi = Wire.read();
Lo = Wire.read();
Config = Wire.read();
Wire.endTransmission();
ADVal = Hi;
ADVal = ADVal * 256 + Lo;
// Serial.print(ADVal, DEC);
//Serial.print(" ");
//Serial.println(Config, DEC);
Serial.print("<");
Serial.print(ADVal);
Serial.print(">");
//lcd.setCursor(0,0);
//lcd.print(ADVal);
lcd.setCursor(0,1);
//float val = ADVal * 0.00006244087;
//lcd.print(val,3);
delay(1);
}
}
and this is the receiving code
#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 5, 4, 3, 2); // initialize the library with the numbers of the interface pins
bool started = false;
bool ended= false;
char inData[10]; // Leave plenty of room
byte index;
float i;
//char inData[24]; // Or whatever size you need
//byte index = 0;
void setup(){
// set up the LCD's number of columns and rows:
lcd.begin(16, 2);
// initialize the serial communications:
Serial.begin(9600);
}
void loop()
{
//Serial.println(s);
while(Serial.available() > 0)
{
char aChar = Serial.read();
if(aChar == '<')
{
// Start of packet marker read
index = 0;
inData[index] = '\0'; // Throw away any incomplete packet
started = true;
ended = false;
}
else if(aChar == '>')
{
// End of packet marker read
ended = true;
break; // Done reading serial data for now
}
else
{
if(index < 10) // Make sure there is room
{
inData[index] = aChar; // Add char to array
index++;
inData[index] = '\0'; // Add NULL to end
}
}
}
// When we get here, there is no more serial data to read,
// or we have read an end-of-packet marker
if(started && ended)
{
// We've seen both markers - do something with the data here
lcd.setCursor(0,0);
i = atoi (inData);
float s = (i * 0.3051851); //multiplying with calibration factor
float value = ( s / 1000 );
lcd.setCursor(1,0);
lcd.print(value,3); // print value after multiplying with calibration factor to LCD
lcd.setCursor(0,1 );
lcd.print(i); // Print raw ADC counts as recieved from transmitter
index = 0;
inData[index] = '\0';
started = false;
ended = false;
}
}
The receiving arduino do get the data through Xbee and it displays values perfectly on the LCD( Attached PIC). I also need to receive the data on a PC attached to the receiving arduino through its USB/Serial port.
When i try to use the serial monitor the display on LCD vanishes and the serial monitor displays garbled values. I thing the Serial.print(s) is sending back the data to the XBEE as both the DO and DI LED starts blinking on the XBEE SHIELD.
I communicate with Arduino via Serial using a program that sends a series of bytes.
In order for the Arduino to realize it is receiving a message rather than junk, I have tagged the start of my byte array with the chars 'S' 'T' 'A' 'R' 'T'. After this will eventually follow a series of bytes that will be assigned to internal variables (not yet implemented).
The Arduino must read each byte sequentially and compare it to the byte array and if all are present in the correct order it will continue with the next part of the program, otherwise it will should discard current byte and wait for more bytes to arrive.
I am trying to implement it in the most efficient and readable way rather than using a series of nested if statements.
So far I have got:
byte inByte = 0;
byte handShake[] = {'S','T','A','R','T'};
void setup() {
Serial.begin(9600);
}
void loop()
{
while (Serial.available())
{
for (int x =0; x < sizeof(handShake) ; x++)
{
inByte = Serial.read();
Serial.println(x);
if (inByte == handShake[x])
{
if (x == (sizeof(handShake)-1)) {setArduino();}
}
else break;
}
}
}
void setArduino () {
Serial.println("Ready To Set Parameters");
}
This however doesn't seem to get past the second byte and I'm not sure why.
Worked it out :
Here is the answer:
byte inByte = 0;
char handShake[] = {'S','T','A','R','T'};
void setup() {
Serial.begin(9600);
}
void loop()
{
while (Serial.available())
{
for (int x =0; x < sizeof(handShake) ; x++)
{
inByte = Serial.read();
Serial.println(x);
if (inByte == handShake[x])
{
if (x == (sizeof(handShake)-1)) {setArduino();}
while(!Serial.available()) {delay(1);}
}
else {break;}
}
}
}
void setArduino () {
Serial.println("Ready To Set Parameters");
}
This may not be the most efficient way perhaps, but I can't see a problem with it currently.
Better answer : This allows the rest of the loop to iterate while waiting for the message to finish and if the full handshake message isn't received the counter will reset.
byte inByte = 0;
char handShake[] = {'S','T','A','R','T'};
int messageIndex = 0;
void setup() {
Serial.begin(9600);
}
void loop()
{
while (Serial.available())
{
inByte = Serial.read();
Serial.println(messageIndex);
if (inByte == handShake[messageIndex])
{
messageIndex++;
if (messageIndex == sizeof(handShake)) {messageIndex = 0; setArduino();}
}
else {messageIndex=0;}
}
// Other code while waiting for message to finish
Serial.println("tick");
}
void setArduino () {
Serial.println("Ready To Set Parameters");
}
You could try to calculate your message. CRC is old and good solution. I use it and it works perfect for me. I am not sure what kind of device are you communicating with.
//define
const uint32_t Polynomial = 0xEDB88320;
const uint16_t NumBytes = 256;
uint8_t data[NumBytes];
/// compute CRC32
uint32_t crc32_bitwise(const void* data, uint16_t length, uint32_t previousCrc32 = 0)
{
uint32_t crc = ~previousCrc32; // same as previousCrc32 ^ 0xFFFFFFFF
uint8_t* current = (uint8_t*) data;
while (length--)
{
crc ^= *current++;
for (uint8_t j = 0; j < 8; j++)
{
uint8_t lowestBit = crc & 1;
crc >>= 1;
if (lowestBit)
crc ^= Polynomial;
}
}
return ~crc; // same as crc ^ 0xFFFFFFFF
}
void setup() {
// put your setup code here, to run once:
}
void loop() {
// put your main code here, to run repeatedly:
}
when you need to calculate CRC
uint32_t crc = crc32_bitwise(data_bytes, sizeof(data_bytes));
data_bytes is byte array.
Then you can get all settings or message in byte data[x] and calculate CRC. Then you can add CRC to the message and send message byte data[x+sizeof(CRC)]
P.S. Use byte instead of int. For ex. for(byte x =0; x<sizeof(handShake); x++)